@caupulican/pi-adaptative 0.94.0 → 0.95.0
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.
- package/CHANGELOG.md +55 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +32 -13
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +7 -4
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +173 -293
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +247 -392
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts +52 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js +118 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.ts +169 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/templates/builder-validator.json +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/templates/provider-prompt-smoke.json +1 -1
- package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +13 -7
- package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +11 -11
- package/dist/core/agent-paths.d.ts +2 -0
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +7 -0
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session.d.ts +11 -41
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +98 -161
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts +6 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +26 -25
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -1
- package/dist/core/autonomy/lane-private-paths.js +2 -1
- package/dist/core/autonomy/lane-private-paths.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +8 -8
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +45 -30
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/worker-session-private-scope.d.ts +12 -0
- package/dist/core/autonomy/worker-session-private-scope.d.ts.map +1 -0
- package/dist/core/autonomy/worker-session-private-scope.js +42 -0
- package/dist/core/autonomy/worker-session-private-scope.js.map +1 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.d.ts +65 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.d.ts.map +1 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.js +145 -0
- package/dist/core/autonomy/worker-tool-adapter-registry.js.map +1 -0
- package/dist/core/background-lane-controller.d.ts +9 -1
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +76 -6
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/background-tool-task-controller.d.ts +23 -2
- package/dist/core/background-tool-task-controller.d.ts.map +1 -1
- package/dist/core/background-tool-task-controller.js +132 -17
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/context/long-term-memory-trigger.d.ts +3 -1
- package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
- package/dist/core/context/long-term-memory-trigger.js +1 -1
- package/dist/core/context/long-term-memory-trigger.js.map +1 -1
- package/dist/core/context/okf-memory-provider.d.ts +3 -0
- package/dist/core/context/okf-memory-provider.d.ts.map +1 -1
- package/dist/core/context/okf-memory-provider.js +66 -31
- package/dist/core/context/okf-memory-provider.js.map +1 -1
- package/dist/core/context/okf-memory.d.ts +18 -1
- package/dist/core/context/okf-memory.d.ts.map +1 -1
- package/dist/core/context/okf-memory.js +48 -0
- package/dist/core/context/okf-memory.js.map +1 -1
- package/dist/core/cost-guard-controller.d.ts +37 -0
- package/dist/core/cost-guard-controller.d.ts.map +1 -0
- package/dist/core/cost-guard-controller.js +71 -0
- package/dist/core/cost-guard-controller.js.map +1 -0
- package/dist/core/cost-guard.d.ts +9 -4
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +7 -3
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +4 -0
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +0 -1
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.d.ts +16 -3
- package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.js +114 -55
- package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
- package/dist/core/delegation/worker-claim.d.ts +1 -2
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +19 -6
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +125 -40
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +3 -3
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js +13 -19
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +3 -2
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +54 -39
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.d.ts +3 -3
- package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.js +7 -7
- package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
- package/dist/core/delegation/worker-machine-scope.d.ts +12 -0
- package/dist/core/delegation/worker-machine-scope.d.ts.map +1 -0
- package/dist/core/delegation/worker-machine-scope.js +38 -0
- package/dist/core/delegation/worker-machine-scope.js.map +1 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts +10 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.js +69 -3
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +6 -1
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +5 -7
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +1 -4
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +3 -2
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.js +50 -25
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
- package/dist/core/durable-custom-message-turn-controller.d.ts +6 -0
- package/dist/core/durable-custom-message-turn-controller.d.ts.map +1 -1
- package/dist/core/durable-custom-message-turn-controller.js +38 -15
- package/dist/core/durable-custom-message-turn-controller.js.map +1 -1
- package/dist/core/extension-binding-controller.d.ts +5 -1
- package/dist/core/extension-binding-controller.d.ts.map +1 -1
- package/dist/core/extension-binding-controller.js +15 -0
- package/dist/core/extension-binding-controller.js.map +1 -1
- package/dist/core/extensions/factory-runtime.d.ts.map +1 -1
- package/dist/core/extensions/factory-runtime.js +5 -0
- package/dist/core/extensions/factory-runtime.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.d.ts +31 -0
- package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +239 -55
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +2 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +8 -0
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +5 -4
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +23 -19
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/learning/auto-learn-settings.d.ts +84 -0
- package/dist/core/learning/auto-learn-settings.d.ts.map +1 -0
- package/dist/core/learning/auto-learn-settings.js +66 -0
- package/dist/core/learning/auto-learn-settings.js.map +1 -0
- package/dist/core/learning/learning-audit.d.ts +5 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js +32 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/reflection-engine.d.ts +24 -0
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +104 -8
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/local-prefix-warm-controller.d.ts +24 -0
- package/dist/core/local-prefix-warm-controller.d.ts.map +1 -0
- package/dist/core/local-prefix-warm-controller.js +79 -0
- package/dist/core/local-prefix-warm-controller.js.map +1 -0
- package/dist/core/memory/okf-project-memory-store.d.ts +28 -0
- package/dist/core/memory/okf-project-memory-store.d.ts.map +1 -0
- package/dist/core/memory/okf-project-memory-store.js +111 -0
- package/dist/core/memory/okf-project-memory-store.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +44 -1
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +341 -24
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory/worker-memory-tools.d.ts +5 -0
- package/dist/core/memory/worker-memory-tools.d.ts.map +1 -0
- package/dist/core/memory/worker-memory-tools.js +5 -0
- package/dist/core/memory/worker-memory-tools.js.map +1 -0
- package/dist/core/memory-controller.d.ts +10 -1
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +72 -8
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/model-capability.d.ts +7 -0
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +12 -0
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +3 -2
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +3 -2
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +16 -12
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +2 -2
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +6 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +14 -0
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/task-profile-writer.d.ts +7 -4
- package/dist/core/orchestration/task-profile-writer.d.ts.map +1 -1
- package/dist/core/orchestration/task-profile-writer.js +71 -59
- package/dist/core/orchestration/task-profile-writer.js.map +1 -1
- package/dist/core/orchestration/thinking-level-schema.d.ts +7 -0
- package/dist/core/orchestration/thinking-level-schema.d.ts.map +1 -0
- package/dist/core/orchestration/thinking-level-schema.js +19 -0
- package/dist/core/orchestration/thinking-level-schema.js.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +12 -5
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/provider-prompt-contracts.d.ts +1 -4
- package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
- package/dist/core/provider-prompt-contracts.js +13 -29
- package/dist/core/provider-prompt-contracts.js.map +1 -1
- package/dist/core/provider-request-context-controller.d.ts +2 -0
- package/dist/core/provider-request-context-controller.d.ts.map +1 -1
- package/dist/core/provider-request-context-controller.js +10 -3
- package/dist/core/provider-request-context-controller.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +63 -27
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +300 -132
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +1 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +25 -14
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +55 -10
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/session-role.d.ts +6 -8
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +8 -18
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +53 -50
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skill-vault.d.ts +15 -0
- package/dist/core/skill-vault.d.ts.map +1 -1
- package/dist/core/skill-vault.js +79 -45
- package/dist/core/skill-vault.js.map +1 -1
- package/dist/core/skills.d.ts +3 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +6 -6
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +2 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +52 -12
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts +3 -0
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +13 -2
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/toolkit/script-runner.d.ts +2 -1
- package/dist/core/toolkit/script-runner.d.ts.map +1 -1
- package/dist/core/toolkit/script-runner.js +10 -2
- package/dist/core/toolkit/script-runner.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +3 -1
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +5 -1
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +4 -13
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +173 -73
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/goal.d.ts +3 -4
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +24 -7
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/profile-writer.d.ts +2 -8
- package/dist/core/tools/profile-writer.d.ts.map +1 -1
- package/dist/core/tools/profile-writer.js +6 -18
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +2 -2
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/core/tools/skill-audit.d.ts +28 -1
- package/dist/core/tools/skill-audit.d.ts.map +1 -1
- package/dist/core/tools/skill-audit.js +56 -12
- package/dist/core/tools/skill-audit.js.map +1 -1
- package/dist/core/tools/skill.d.ts +12 -1
- package/dist/core/tools/skill.d.ts.map +1 -1
- package/dist/core/tools/skill.js +52 -0
- package/dist/core/tools/skill.js.map +1 -1
- package/dist/core/tools/skillify.d.ts.map +1 -1
- package/dist/core/tools/skillify.js +16 -7
- package/dist/core/tools/skillify.js.map +1 -1
- package/dist/core/tools/task-steps.js +1 -1
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +4 -16
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js +5 -20
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/tools/tool-task.d.ts +1 -0
- package/dist/core/tools/tool-task.d.ts.map +1 -1
- package/dist/core/tools/tool-task.js +13 -8
- package/dist/core/tools/tool-task.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +2 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +4 -0
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/core/worktree-sync/codes.d.ts +1 -2
- package/dist/core/worktree-sync/codes.d.ts.map +1 -1
- package/dist/core/worktree-sync/codes.js +1 -2
- package/dist/core/worktree-sync/codes.js.map +1 -1
- package/dist/core/worktree-sync/lane-gate.d.ts +4 -8
- package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -1
- package/dist/core/worktree-sync/lane-gate.js +5 -51
- package/dist/core/worktree-sync/lane-gate.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts +6 -7
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +32 -207
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/autonomy-commands.js +2 -2
- package/dist/modes/interactive/autonomy-commands.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
- package/dist/modes/interactive/components/activity-lane.js +12 -23
- package/dist/modes/interactive/components/activity-lane.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +142 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.js +2 -2
- package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +150 -73
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +8 -4
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.js +10 -0
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
- package/docs/extensions.md +8 -0
- package/docs/harness-architecture.md +28 -32
- package/docs/index.md +1 -1
- package/docs/process-matrix.md +8 -6
- package/docs/resources.md +1 -1
- package/docs/settings.md +61 -51
- package/docs/tmux-agent-manager.md +47 -40
- package/docs/usage.md +1 -1
- package/docs/worker-profiles.md +8 -6
- package/docs/worktree-sync.md +26 -20
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +0 -133
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +0 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +0 -199
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +0 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +0 -312
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-fleet-limits.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-fleet-limits.ts"],"names":[],"mappings":"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","sourcesContent":["import { latestAgentAttemptByDurableOrder } from \"../orchestration/attempt-ordering.ts\";\nimport {\n\ttype AgentBindingContract,\n\tMAX_ORCHESTRATION_AGENT_BINDINGS,\n\tMAX_ORCHESTRATION_AGENT_DEPTH,\n\tMAX_ORCHESTRATION_DIRECT_CHILDREN,\n\ttype OrchestrationDelegationLimits,\n} from \"../orchestration/contracts.ts\";\nimport type { AttemptRuntimeState, TaskRuntimeProjection } from \"../orchestration/task-runtime.ts\";\n\n/**\n * Process-independent safety ceilings for one durable session fleet. These limits bound persisted\n * identity growth and scheduler fan-out; model/provider budgets remain separately authoritative.\n */\nexport interface WorkerFleetLimits {\n\tmaxDepth: number;\n\tmaxAgentsPerSession: number;\n\tmaxChildrenPerAgent: number;\n\tmaxNestedAgentsPerSession: number;\n\tmaxQueuedDispatches: number;\n}\n\nexport const DEFAULT_WORKER_FLEET_LIMITS: Readonly<WorkerFleetLimits> = Object.freeze({\n\tmaxDepth: MAX_ORCHESTRATION_AGENT_DEPTH,\n\tmaxAgentsPerSession: MAX_ORCHESTRATION_AGENT_BINDINGS,\n\tmaxChildrenPerAgent: MAX_ORCHESTRATION_DIRECT_CHILDREN,\n\tmaxNestedAgentsPerSession: MAX_ORCHESTRATION_AGENT_BINDINGS,\n\tmaxQueuedDispatches: 256,\n});\n\n/** Profile-free workers get one useful nested identity without an open-ended recursive fleet. */\nexport const LEAN_WORKER_DELEGATION_LIMITS: Readonly<OrchestrationDelegationLimits> = Object.freeze({\n\tmaxDepth: 1,\n\tmaxChildrenPerAgent: 1,\n\tmaxNestedAgentsPerSession: 1,\n});\n\n/** Materialize an optional profile limit inside the process-independent host safety ceiling. */\nexport function resolveWorkerFleetLimits(\n\tdelegationLimits?: Readonly<OrchestrationDelegationLimits>,\n): Readonly<WorkerFleetLimits> {\n\treturn {\n\t\t...DEFAULT_WORKER_FLEET_LIMITS,\n\t\tmaxDepth: Math.min(\n\t\t\tdelegationLimits?.maxDepth ?? DEFAULT_WORKER_FLEET_LIMITS.maxDepth,\n\t\t\tMAX_ORCHESTRATION_AGENT_DEPTH,\n\t\t),\n\t\tmaxChildrenPerAgent: Math.min(\n\t\t\tdelegationLimits?.maxChildrenPerAgent ?? DEFAULT_WORKER_FLEET_LIMITS.maxChildrenPerAgent,\n\t\t\tMAX_ORCHESTRATION_DIRECT_CHILDREN,\n\t\t),\n\t\tmaxNestedAgentsPerSession: Math.min(\n\t\t\tdelegationLimits?.maxNestedAgentsPerSession ?? DEFAULT_WORKER_FLEET_LIMITS.maxNestedAgentsPerSession,\n\t\t\tMAX_ORCHESTRATION_AGENT_BINDINGS,\n\t\t),\n\t};\n}\n\n/** Descendant routing may preserve or narrow an ancestor's recursive authority, never widen it. */\nexport function intersectWorkerDelegationLimits(\n\trequested?: Readonly<OrchestrationDelegationLimits>,\n\tboundary?: Readonly<OrchestrationDelegationLimits>,\n): OrchestrationDelegationLimits | undefined {\n\tif (!requested && !boundary) return undefined;\n\tconst requestedLimits = resolveWorkerFleetLimits(requested);\n\tconst boundaryLimits = resolveWorkerFleetLimits(boundary);\n\treturn {\n\t\tmaxDepth: Math.min(requestedLimits.maxDepth, boundaryLimits.maxDepth),\n\t\tmaxChildrenPerAgent: Math.min(requestedLimits.maxChildrenPerAgent, boundaryLimits.maxChildrenPerAgent),\n\t\tmaxNestedAgentsPerSession: Math.min(\n\t\t\trequestedLimits.maxNestedAgentsPerSession,\n\t\t\tboundaryLimits.maxNestedAgentsPerSession,\n\t\t),\n\t};\n}\n\nexport type NewWorkerAdmission =\n\t| { ok: true; depth: number }\n\t| {\n\t\t\tok: false;\n\t\t\treasonCode:\n\t\t\t\t| \"worker_agent_parent_unknown\"\n\t\t\t\t| \"worker_agent_parent_retired\"\n\t\t\t\t| \"worker_agent_depth_limit_reached\"\n\t\t\t\t| \"worker_agent_child_limit_reached\"\n\t\t\t\t| \"worker_agent_nested_session_limit_reached\"\n\t\t\t\t| \"worker_agent_session_limit_reached\";\n\t };\n\nexport type WorkerIdentityHeadroomAdmission =\n\t| { ok: true }\n\t| { ok: false; reasonCode: \"worker_agent_session_limit_reached\" };\n\n/** Subjects whose admitted verifier identity has not yet been materialized. */\nexport function pendingVerifierSubjectTaskIds(\n\tsnapshot: Pick<TaskRuntimeProjection, \"agents\" | \"tasks\" | \"attempts\">,\n): Set<string> {\n\tconst agents = snapshot.agents ?? {};\n\tconst tasks = snapshot.tasks ?? {};\n\tconst attempts = snapshot.attempts ?? {};\n\tconst pending = new Set<string>();\n\tfor (const taskId in tasks) {\n\t\tif (!Object.hasOwn(tasks, taskId)) continue;\n\t\tconst subject = tasks[taskId];\n\t\tif (!subject || subject.verification) continue;\n\t\tlet attempt: AttemptRuntimeState | undefined;\n\t\tfor (let index = subject.attemptIds.length - 1; index >= 0; index -= 1) {\n\t\t\tattempt = attempts[subject.attemptIds[index]!];\n\t\t\tif (attempt) break;\n\t\t}\n\t\tif (!attempt?.dispatch.executionContract?.verifier) continue;\n\t\tif (\n\t\t\tattempt.status === \"queued\" ||\n\t\t\tattempt.status === \"leased\" ||\n\t\t\tattempt.status === \"running\" ||\n\t\t\tattempt.status === \"suspended\" ||\n\t\t\tattempt.result?.nextAction === \"independent_verification_required\"\n\t\t) {\n\t\t\tpending.add(subject.task.taskId);\n\t\t}\n\t}\n\tif (pending.size === 0) return pending;\n\tfor (const taskId in tasks) {\n\t\tif (!Object.hasOwn(tasks, taskId)) continue;\n\t\tconst verifierTask = tasks[taskId];\n\t\tconst verificationOfTaskId = verifierTask?.task.verificationOfTaskId;\n\t\tif (!verifierTask || !verificationOfTaskId || !pending.has(verificationOfTaskId)) continue;\n\t\tlet verifierAttempt: AttemptRuntimeState | undefined;\n\t\tfor (let index = verifierTask.attemptIds.length - 1; index >= 0; index -= 1) {\n\t\t\tverifierAttempt = attempts[verifierTask.attemptIds[index]!];\n\t\t\tif (verifierAttempt) break;\n\t\t}\n\t\tconst verifierAgentId =\n\t\t\tverifierAttempt?.agentId ?? verifierAttempt?.dispatch.logicalLaneId ?? verifierTask.task.taskId;\n\t\tif (agents[verifierAgentId]) pending.delete(verificationOfTaskId);\n\t\tif (pending.size === 0) break;\n\t}\n\treturn pending;\n}\n\n/** Reserve durable identity slots without applying parent depth or direct-child limits. */\nfunction evaluateWorkerIdentityHeadroom(\n\tagents: Readonly<Record<string, AgentBindingContract>>,\n\trequiredAgentSlots: number,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): WorkerIdentityHeadroomAdmission {\n\tif (!Number.isSafeInteger(requiredAgentSlots) || requiredAgentSlots < 0) {\n\t\tthrow new TypeError(\"requiredAgentSlots must be a non-negative safe integer.\");\n\t}\n\treturn requiredAgentSlots > limits.maxAgentsPerSession - Object.keys(agents).length\n\t\t? { ok: false, reasonCode: \"worker_agent_session_limit_reached\" }\n\t\t: { ok: true };\n}\n\n/**\n * A persistent-agent turn consumes no implementation identity, but its retained immutable contract\n * can still require a fresh verifier. Protect both that verifier and every earlier reservation.\n */\nexport function evaluateReusableWorkerTaskAdmission(\n\tsnapshot: Pick<TaskRuntimeProjection, \"agents\" | \"tasks\" | \"attempts\">,\n\tagentId: string,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): WorkerIdentityHeadroomAdmission {\n\tconst latestAttempt = latestAgentAttemptByDurableOrder(snapshot, agentId);\n\tconst requiredAgentSlots =\n\t\tpendingVerifierSubjectTaskIds(snapshot).size + (latestAttempt?.dispatch.executionContract?.verifier ? 1 : 0);\n\treturn evaluateWorkerIdentityHeadroom(snapshot.agents, requiredAgentSlots, limits);\n}\n\n/** Evaluate a new durable identity before a task, conversation, or scheduler entry is created. */\nexport function evaluateNewWorkerAdmission(\n\tagents: Readonly<Record<string, AgentBindingContract>>,\n\tparentAgentId?: string,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n\trequiredAgentSlots = 1,\n): NewWorkerAdmission {\n\tif (!Number.isSafeInteger(requiredAgentSlots) || requiredAgentSlots < 1) {\n\t\tthrow new TypeError(\"requiredAgentSlots must be a positive safe integer.\");\n\t}\n\tconst headroom = evaluateWorkerIdentityHeadroom(agents, requiredAgentSlots, limits);\n\tif (!headroom.ok) return headroom;\n\tif (!parentAgentId) return { ok: true, depth: 0 };\n\tconst parent = agents[parentAgentId];\n\tif (!parent) return { ok: false, reasonCode: \"worker_agent_parent_unknown\" };\n\tif (parent.status === \"retired\") return { ok: false, reasonCode: \"worker_agent_parent_retired\" };\n\tconst depth = parent.depth + 1;\n\tif (depth > limits.maxDepth) return { ok: false, reasonCode: \"worker_agent_depth_limit_reached\" };\n\tlet directChildren = 0;\n\tfor (const agent of Object.values(agents)) {\n\t\tif (agent.parentAgentId === parent.agentId) directChildren += 1;\n\t}\n\tif (directChildren >= limits.maxChildrenPerAgent) {\n\t\treturn { ok: false, reasonCode: \"worker_agent_child_limit_reached\" };\n\t}\n\tlet nestedAgents = 0;\n\tfor (const agent of Object.values(agents)) {\n\t\t// A retired agent's durable identity slot is still reserved (evaluateWorkerIdentityHeadroom\n\t\t// above already bounds total agent count), but it no longer occupies a live nested-fleet\n\t\t// slot. Counting it here permanently blocks all future nested delegation once any nested\n\t\t// child has ever finished — with LEAN_WORKER_DELEGATION_LIMITS (=1), a single retired child.\n\t\tif (agent.parentAgentId && agent.status !== \"retired\") nestedAgents += 1;\n\t}\n\tif (nestedAgents >= limits.maxNestedAgentsPerSession) {\n\t\treturn { ok: false, reasonCode: \"worker_agent_nested_session_limit_reached\" };\n\t}\n\treturn { ok: true, depth };\n}\n\n/** Keep one queue slot reserved for an already-admitted mandatory verifier. */\nexport function workerQueueHasCapacity(\n\tqueuedCount: number,\n\tpriority: boolean,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): boolean {\n\tif (!Number.isSafeInteger(queuedCount) || queuedCount < 0) return false;\n\tconst ceiling = priority ? limits.maxQueuedDispatches : limits.maxQueuedDispatches - 1;\n\treturn queuedCount < ceiling;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-fleet-limits.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-fleet-limits.ts"],"names":[],"mappings":"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","sourcesContent":["import { latestAgentAttemptByDurableOrder } from \"../orchestration/attempt-ordering.ts\";\nimport {\n\ttype AgentBindingContract,\n\tMAX_ORCHESTRATION_AGENT_BINDINGS,\n\tMAX_ORCHESTRATION_AGENT_DEPTH,\n\tMAX_ORCHESTRATION_DIRECT_CHILDREN,\n\ttype OrchestrationDelegationLimits,\n} from \"../orchestration/contracts.ts\";\nimport type { AttemptRuntimeState, TaskRuntimeProjection } from \"../orchestration/task-runtime.ts\";\n\n/**\n * Process-independent safety ceilings for one durable session fleet. These limits bound persisted\n * identity growth and scheduler fan-out; model/provider budgets remain separately authoritative.\n */\nexport interface WorkerFleetLimits {\n\tmaxDepth: number;\n\tmaxAgentsPerSession: number;\n\tmaxChildrenPerAgent: number;\n\tmaxNestedAgentsPerSession: number;\n\tmaxQueuedDispatches: number;\n}\n\nexport const DEFAULT_WORKER_FLEET_LIMITS: Readonly<WorkerFleetLimits> = Object.freeze({\n\tmaxDepth: MAX_ORCHESTRATION_AGENT_DEPTH,\n\tmaxAgentsPerSession: MAX_ORCHESTRATION_AGENT_BINDINGS,\n\tmaxChildrenPerAgent: MAX_ORCHESTRATION_DIRECT_CHILDREN,\n\tmaxNestedAgentsPerSession: MAX_ORCHESTRATION_AGENT_BINDINGS,\n\tmaxQueuedDispatches: 256,\n});\n\n/** Every newly compiled native worker is a leaf; legacy wider limits are narrowed to this contract. */\nexport const LEAF_WORKER_DELEGATION_LIMITS: Readonly<OrchestrationDelegationLimits> = Object.freeze({\n\tmaxDepth: 0,\n\tmaxChildrenPerAgent: 0,\n\tmaxNestedAgentsPerSession: 0,\n});\n\n/** Materialize an optional profile limit inside the process-independent host safety ceiling. */\nexport function resolveWorkerFleetLimits(\n\tdelegationLimits?: Readonly<OrchestrationDelegationLimits>,\n): Readonly<WorkerFleetLimits> {\n\treturn {\n\t\t...DEFAULT_WORKER_FLEET_LIMITS,\n\t\tmaxDepth: Math.min(\n\t\t\tdelegationLimits?.maxDepth ?? DEFAULT_WORKER_FLEET_LIMITS.maxDepth,\n\t\t\tMAX_ORCHESTRATION_AGENT_DEPTH,\n\t\t),\n\t\tmaxChildrenPerAgent: Math.min(\n\t\t\tdelegationLimits?.maxChildrenPerAgent ?? DEFAULT_WORKER_FLEET_LIMITS.maxChildrenPerAgent,\n\t\t\tMAX_ORCHESTRATION_DIRECT_CHILDREN,\n\t\t),\n\t\tmaxNestedAgentsPerSession: Math.min(\n\t\t\tdelegationLimits?.maxNestedAgentsPerSession ?? DEFAULT_WORKER_FLEET_LIMITS.maxNestedAgentsPerSession,\n\t\t\tMAX_ORCHESTRATION_AGENT_BINDINGS,\n\t\t),\n\t};\n}\n\n/** Legacy recovery may preserve or narrow a persisted lineage boundary, never widen it. */\nexport function intersectWorkerDelegationLimits(\n\trequested?: Readonly<OrchestrationDelegationLimits>,\n\tboundary?: Readonly<OrchestrationDelegationLimits>,\n): OrchestrationDelegationLimits | undefined {\n\tif (!requested && !boundary) return undefined;\n\tconst requestedLimits = resolveWorkerFleetLimits(requested);\n\tconst boundaryLimits = resolveWorkerFleetLimits(boundary);\n\treturn {\n\t\tmaxDepth: Math.min(requestedLimits.maxDepth, boundaryLimits.maxDepth),\n\t\tmaxChildrenPerAgent: Math.min(requestedLimits.maxChildrenPerAgent, boundaryLimits.maxChildrenPerAgent),\n\t\tmaxNestedAgentsPerSession: Math.min(\n\t\t\trequestedLimits.maxNestedAgentsPerSession,\n\t\t\tboundaryLimits.maxNestedAgentsPerSession,\n\t\t),\n\t};\n}\n\nexport type NewWorkerAdmission =\n\t| { ok: true; depth: number }\n\t| {\n\t\t\tok: false;\n\t\t\treasonCode:\n\t\t\t\t| \"worker_agent_parent_unknown\"\n\t\t\t\t| \"worker_agent_parent_retired\"\n\t\t\t\t| \"worker_agent_depth_limit_reached\"\n\t\t\t\t| \"worker_agent_child_limit_reached\"\n\t\t\t\t| \"worker_agent_nested_session_limit_reached\"\n\t\t\t\t| \"worker_agent_session_limit_reached\";\n\t };\n\nexport type WorkerIdentityHeadroomAdmission =\n\t| { ok: true }\n\t| { ok: false; reasonCode: \"worker_agent_session_limit_reached\" };\n\n/** Subjects whose admitted verifier identity has not yet been materialized. */\nexport function pendingVerifierSubjectTaskIds(\n\tsnapshot: Pick<TaskRuntimeProjection, \"agents\" | \"tasks\" | \"attempts\">,\n): Set<string> {\n\tconst agents = snapshot.agents ?? {};\n\tconst tasks = snapshot.tasks ?? {};\n\tconst attempts = snapshot.attempts ?? {};\n\tconst pending = new Set<string>();\n\tfor (const taskId in tasks) {\n\t\tif (!Object.hasOwn(tasks, taskId)) continue;\n\t\tconst subject = tasks[taskId];\n\t\tif (!subject || subject.verification) continue;\n\t\tlet attempt: AttemptRuntimeState | undefined;\n\t\tfor (let index = subject.attemptIds.length - 1; index >= 0; index -= 1) {\n\t\t\tattempt = attempts[subject.attemptIds[index]!];\n\t\t\tif (attempt) break;\n\t\t}\n\t\tif (!attempt?.dispatch.executionContract?.verifier) continue;\n\t\tif (\n\t\t\tattempt.status === \"queued\" ||\n\t\t\tattempt.status === \"leased\" ||\n\t\t\tattempt.status === \"running\" ||\n\t\t\tattempt.status === \"suspended\" ||\n\t\t\tattempt.result?.nextAction === \"independent_verification_required\"\n\t\t) {\n\t\t\tpending.add(subject.task.taskId);\n\t\t}\n\t}\n\tif (pending.size === 0) return pending;\n\tfor (const taskId in tasks) {\n\t\tif (!Object.hasOwn(tasks, taskId)) continue;\n\t\tconst verifierTask = tasks[taskId];\n\t\tconst verificationOfTaskId = verifierTask?.task.verificationOfTaskId;\n\t\tif (!verifierTask || !verificationOfTaskId || !pending.has(verificationOfTaskId)) continue;\n\t\tlet verifierAttempt: AttemptRuntimeState | undefined;\n\t\tfor (let index = verifierTask.attemptIds.length - 1; index >= 0; index -= 1) {\n\t\t\tverifierAttempt = attempts[verifierTask.attemptIds[index]!];\n\t\t\tif (verifierAttempt) break;\n\t\t}\n\t\tconst verifierAgentId =\n\t\t\tverifierAttempt?.agentId ?? verifierAttempt?.dispatch.logicalLaneId ?? verifierTask.task.taskId;\n\t\tif (agents[verifierAgentId]) pending.delete(verificationOfTaskId);\n\t\tif (pending.size === 0) break;\n\t}\n\treturn pending;\n}\n\n/** Reserve durable identity slots without applying parent depth or direct-child limits. */\nfunction evaluateWorkerIdentityHeadroom(\n\tagents: Readonly<Record<string, AgentBindingContract>>,\n\trequiredAgentSlots: number,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): WorkerIdentityHeadroomAdmission {\n\tif (!Number.isSafeInteger(requiredAgentSlots) || requiredAgentSlots < 0) {\n\t\tthrow new TypeError(\"requiredAgentSlots must be a non-negative safe integer.\");\n\t}\n\treturn requiredAgentSlots > limits.maxAgentsPerSession - Object.keys(agents).length\n\t\t? { ok: false, reasonCode: \"worker_agent_session_limit_reached\" }\n\t\t: { ok: true };\n}\n\n/**\n * A persistent-agent turn consumes no implementation identity, but its retained immutable contract\n * can still require a fresh verifier. Protect both that verifier and every earlier reservation.\n */\nexport function evaluateReusableWorkerTaskAdmission(\n\tsnapshot: Pick<TaskRuntimeProjection, \"agents\" | \"tasks\" | \"attempts\">,\n\tagentId: string,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): WorkerIdentityHeadroomAdmission {\n\tconst latestAttempt = latestAgentAttemptByDurableOrder(snapshot, agentId);\n\tconst requiredAgentSlots =\n\t\tpendingVerifierSubjectTaskIds(snapshot).size + (latestAttempt?.dispatch.executionContract?.verifier ? 1 : 0);\n\treturn evaluateWorkerIdentityHeadroom(snapshot.agents, requiredAgentSlots, limits);\n}\n\n/** Evaluate a new durable identity before a task, conversation, or scheduler entry is created. */\nexport function evaluateNewWorkerAdmission(\n\tagents: Readonly<Record<string, AgentBindingContract>>,\n\tparentAgentId?: string,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n\trequiredAgentSlots = 1,\n): NewWorkerAdmission {\n\tif (!Number.isSafeInteger(requiredAgentSlots) || requiredAgentSlots < 1) {\n\t\tthrow new TypeError(\"requiredAgentSlots must be a positive safe integer.\");\n\t}\n\tconst headroom = evaluateWorkerIdentityHeadroom(agents, requiredAgentSlots, limits);\n\tif (!headroom.ok) return headroom;\n\tif (!parentAgentId) return { ok: true, depth: 0 };\n\tconst parent = agents[parentAgentId];\n\tif (!parent) return { ok: false, reasonCode: \"worker_agent_parent_unknown\" };\n\tif (parent.status === \"retired\") return { ok: false, reasonCode: \"worker_agent_parent_retired\" };\n\tconst depth = parent.depth + 1;\n\tif (depth > limits.maxDepth) return { ok: false, reasonCode: \"worker_agent_depth_limit_reached\" };\n\tlet directChildren = 0;\n\tfor (const agent of Object.values(agents)) {\n\t\tif (agent.parentAgentId === parent.agentId) directChildren += 1;\n\t}\n\tif (directChildren >= limits.maxChildrenPerAgent) {\n\t\treturn { ok: false, reasonCode: \"worker_agent_child_limit_reached\" };\n\t}\n\tlet nestedAgents = 0;\n\tfor (const agent of Object.values(agents)) {\n\t\t// A retired agent's durable identity slot is still reserved (evaluateWorkerIdentityHeadroom\n\t\t// above already bounds total agent count), but it no longer occupies a live nested-fleet\n\t\t// slot. Counting it here permanently blocks all future nested delegation once any nested\n\t\t// child has ever finished when a recovered legacy contract retains a nested-session limit of one.\n\t\tif (agent.parentAgentId && agent.status !== \"retired\") nestedAgents += 1;\n\t}\n\tif (nestedAgents >= limits.maxNestedAgentsPerSession) {\n\t\treturn { ok: false, reasonCode: \"worker_agent_nested_session_limit_reached\" };\n\t}\n\treturn { ok: true, depth };\n}\n\n/** Keep one queue slot reserved for an already-admitted mandatory verifier. */\nexport function workerQueueHasCapacity(\n\tqueuedCount: number,\n\tpriority: boolean,\n\tlimits: Readonly<WorkerFleetLimits> = DEFAULT_WORKER_FLEET_LIMITS,\n): boolean {\n\tif (!Number.isSafeInteger(queuedCount) || queuedCount < 0) return false;\n\tconst ceiling = priority ? limits.maxQueuedDispatches : limits.maxQueuedDispatches - 1;\n\treturn queuedCount < ceiling;\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type PathExists = (candidate: string) => boolean;
|
|
2
|
+
/** Preserve native Windows absolute paths when the host process is running under another path dialect. */
|
|
3
|
+
export declare function resolveWorkerWorkspacePath(cwd: string, candidate: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve every local filesystem root the host can address without hard-coding POSIX `/` or
|
|
6
|
+
* collapsing Windows authority to the foreground drive. WSL exposes mounted drives below its
|
|
7
|
+
* POSIX root, while native Windows requires one root per mounted drive. A UNC working directory
|
|
8
|
+
* contributes its share root even though drive enumeration cannot discover remote shares.
|
|
9
|
+
*/
|
|
10
|
+
export declare function workerMachinePathRoots(cwd: string, platform?: NodeJS.Platform, pathExists?: PathExists): string[];
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=worker-machine-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-machine-scope.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-machine-scope.ts"],"names":[],"mappings":"AAGA,KAAK,UAAU,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;AAEjD,0GAA0G;AAC1G,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIjF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,UAAU,GAAE,UAAuB,GACjC,MAAM,EAAE,CAkBV"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/** Preserve native Windows absolute paths when the host process is running under another path dialect. */
|
|
4
|
+
export function resolveWorkerWorkspacePath(cwd, candidate) {
|
|
5
|
+
if (path.isAbsolute(candidate))
|
|
6
|
+
return path.resolve(candidate);
|
|
7
|
+
if (path.win32.isAbsolute(candidate))
|
|
8
|
+
return path.win32.normalize(candidate);
|
|
9
|
+
return path.resolve(cwd, candidate);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve every local filesystem root the host can address without hard-coding POSIX `/` or
|
|
13
|
+
* collapsing Windows authority to the foreground drive. WSL exposes mounted drives below its
|
|
14
|
+
* POSIX root, while native Windows requires one root per mounted drive. A UNC working directory
|
|
15
|
+
* contributes its share root even though drive enumeration cannot discover remote shares.
|
|
16
|
+
*/
|
|
17
|
+
export function workerMachinePathRoots(cwd, platform = process.platform, pathExists = existsSync) {
|
|
18
|
+
if (platform !== "win32")
|
|
19
|
+
return [path.posix.parse(path.posix.resolve(cwd)).root];
|
|
20
|
+
const roots = new Map();
|
|
21
|
+
const addRoot = (candidate) => {
|
|
22
|
+
const normalized = path.win32.normalize(candidate);
|
|
23
|
+
const canonical = /^[a-z]:\\$/i.test(normalized)
|
|
24
|
+
? `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)}`
|
|
25
|
+
: normalized;
|
|
26
|
+
roots.set(canonical.toLowerCase(), canonical);
|
|
27
|
+
};
|
|
28
|
+
const currentRoot = path.win32.parse(path.win32.resolve(cwd)).root;
|
|
29
|
+
if (currentRoot)
|
|
30
|
+
addRoot(currentRoot);
|
|
31
|
+
for (let code = "A".charCodeAt(0); code <= "Z".charCodeAt(0); code += 1) {
|
|
32
|
+
const root = `${String.fromCharCode(code)}:\\`;
|
|
33
|
+
if (pathExists(root))
|
|
34
|
+
addRoot(root);
|
|
35
|
+
}
|
|
36
|
+
return [...roots.values()].sort((left, right) => left.localeCompare(right));
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=worker-machine-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-machine-scope.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-machine-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,0GAA0G;AAC1G,MAAM,UAAU,0BAA0B,CAAC,GAAW,EAAE,SAAiB;IACxE,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACrC,GAAW,EACX,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAC5C,UAAU,GAAe,UAAU;IAEnC,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAElF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAQ,EAAE;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC;YAC/C,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC/D,CAAC,CAAC,UAAU,CAAC;QACd,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,IAAI,WAAW;QAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/C,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\ntype PathExists = (candidate: string) => boolean;\n\n/** Preserve native Windows absolute paths when the host process is running under another path dialect. */\nexport function resolveWorkerWorkspacePath(cwd: string, candidate: string): string {\n\tif (path.isAbsolute(candidate)) return path.resolve(candidate);\n\tif (path.win32.isAbsolute(candidate)) return path.win32.normalize(candidate);\n\treturn path.resolve(cwd, candidate);\n}\n\n/**\n * Resolve every local filesystem root the host can address without hard-coding POSIX `/` or\n * collapsing Windows authority to the foreground drive. WSL exposes mounted drives below its\n * POSIX root, while native Windows requires one root per mounted drive. A UNC working directory\n * contributes its share root even though drive enumeration cannot discover remote shares.\n */\nexport function workerMachinePathRoots(\n\tcwd: string,\n\tplatform: NodeJS.Platform = process.platform,\n\tpathExists: PathExists = existsSync,\n): string[] {\n\tif (platform !== \"win32\") return [path.posix.parse(path.posix.resolve(cwd)).root];\n\n\tconst roots = new Map<string, string>();\n\tconst addRoot = (candidate: string): void => {\n\t\tconst normalized = path.win32.normalize(candidate);\n\t\tconst canonical = /^[a-z]:\\\\$/i.test(normalized)\n\t\t\t? `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)}`\n\t\t\t: normalized;\n\t\troots.set(canonical.toLowerCase(), canonical);\n\t};\n\tconst currentRoot = path.win32.parse(path.win32.resolve(cwd)).root;\n\tif (currentRoot) addRoot(currentRoot);\n\tfor (let code = \"A\".charCodeAt(0); code <= \"Z\".charCodeAt(0); code += 1) {\n\t\tconst root = `${String.fromCharCode(code)}:\\\\`;\n\t\tif (pathExists(root)) addRoot(root);\n\t}\n\treturn [...roots.values()].sort((left, right) => left.localeCompare(right));\n}\n"]}
|
|
@@ -2,9 +2,12 @@ import type { LaneRecord, LaneTerminalStatus } from "../autonomy/lane-tracker.ts
|
|
|
2
2
|
export interface WorkerTerminalHandoffRecord {
|
|
3
3
|
laneId: string;
|
|
4
4
|
status: LaneTerminalStatus;
|
|
5
|
+
completedAt?: string;
|
|
5
6
|
reasonCode?: string;
|
|
6
7
|
/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */
|
|
7
8
|
goalId?: string;
|
|
9
|
+
/** Runtime-only receipt. Observation consumes delivery, never mutation review. */
|
|
10
|
+
observedAt?: string;
|
|
8
11
|
}
|
|
9
12
|
export interface WorkerNotificationStatus {
|
|
10
13
|
active: number;
|
|
@@ -22,6 +25,8 @@ export interface WorkerNotificationCoordinatorOptions {
|
|
|
22
25
|
notify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;
|
|
23
26
|
warn(message: string): void;
|
|
24
27
|
markDurableDelivered(notificationIds: readonly string[]): void;
|
|
28
|
+
/** Active event-driven waits consume matching terminals before a second foreground wake is admitted. */
|
|
29
|
+
isObserved?(record: LaneRecord): boolean;
|
|
25
30
|
}
|
|
26
31
|
/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */
|
|
27
32
|
export declare class WorkerNotificationCoordinator {
|
|
@@ -37,15 +42,20 @@ export declare class WorkerNotificationCoordinator {
|
|
|
37
42
|
* an owning caller can durably persist and replay them across a process restart.
|
|
38
43
|
*/
|
|
39
44
|
private readonly inFlight;
|
|
45
|
+
private readonly observedTerminals;
|
|
40
46
|
private scheduled;
|
|
41
47
|
private disposed;
|
|
42
48
|
private deliveryTail;
|
|
43
49
|
private retryTimer;
|
|
50
|
+
private readonly handoffWatchdogs;
|
|
44
51
|
private retryCount;
|
|
45
52
|
constructor(options: WorkerNotificationCoordinatorOptions);
|
|
46
53
|
/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */
|
|
47
54
|
getOutstandingRecords(): readonly WorkerTerminalHandoffRecord[];
|
|
48
55
|
recordTerminal(record: LaneRecord, durableNotificationId?: string): void;
|
|
56
|
+
/** Mark exact terminal generations as already exposed to the parent model. */
|
|
57
|
+
observeTerminals(records: readonly Pick<LaneRecord, "laneId" | "status" | "completedAt" | "reasonCode">[], observedAt?: string): void;
|
|
58
|
+
private rememberObserved;
|
|
49
59
|
statusChanged(): void;
|
|
50
60
|
/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */
|
|
51
61
|
dispose(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-notification-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"worker-notification-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAsBlF,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yGAAyG;IACzG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAC3D;AAQD,MAAM,WAAW,oCAAoC;IACpD,gBAAgB,IAAI,SAAS,UAAU,EAAE,CAAC;IAC1C,UAAU,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACnD,MAAM,CAAC,OAAO,EAAE,SAAS,2BAA2B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/D,wGAAwG;IACxG,UAAU,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC;CACzC;AAMD,sGAAsG;AACtG,qBAAa,6BAA6B;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgD;IACxE;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;IACzE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4C;IAC7E,OAAO,CAAC,UAAU,CAAK;IAEvB,YAAY,OAAO,EAAE,oCAAoC,EAExD;IAED,qGAAqG;IACrG,qBAAqB,IAAI,SAAS,2BAA2B,EAAE,CAE9D;IAED,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAiCvE;IAED,8EAA8E;IAC9E,gBAAgB,CACf,OAAO,EAAE,SAAS,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC,EAAE,EACxF,UAAU,SAA2B,GACnC,IAAI,CAMN;IAED,OAAO,CAAC,gBAAgB;IAUxB,aAAa,IAAI,IAAI,CAEpB;IAED,qGAAqG;IACrG,OAAO,IAAI,IAAI,CAUd;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,KAAK;CAiFb"}
|
|
@@ -15,6 +15,10 @@ const ATTENTION_TERMINAL_STATUSES = new Set(["partial", "blocked", "canceled"]);
|
|
|
15
15
|
* subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.
|
|
16
16
|
*/
|
|
17
17
|
const HANDOFF_WATCHDOG_MS = 1_800_000;
|
|
18
|
+
const MAX_OBSERVED_TERMINALS = 512;
|
|
19
|
+
function terminalIdentity(record) {
|
|
20
|
+
return [record.laneId, record.completedAt ?? "", record.status, record.reasonCode ?? ""].join("\0");
|
|
21
|
+
}
|
|
18
22
|
/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */
|
|
19
23
|
export class WorkerNotificationCoordinator {
|
|
20
24
|
constructor(options) {
|
|
@@ -29,9 +33,11 @@ export class WorkerNotificationCoordinator {
|
|
|
29
33
|
* an owning caller can durably persist and replay them across a process restart.
|
|
30
34
|
*/
|
|
31
35
|
this.inFlight = new Map();
|
|
36
|
+
this.observedTerminals = new Map();
|
|
32
37
|
this.scheduled = false;
|
|
33
38
|
this.disposed = false;
|
|
34
39
|
this.deliveryTail = Promise.resolve();
|
|
40
|
+
this.handoffWatchdogs = new Set();
|
|
35
41
|
this.retryCount = 0;
|
|
36
42
|
this.options = options;
|
|
37
43
|
}
|
|
@@ -43,18 +49,58 @@ export class WorkerNotificationCoordinator {
|
|
|
43
49
|
if (record.status === "queued" || record.status === "running")
|
|
44
50
|
return;
|
|
45
51
|
const key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;
|
|
52
|
+
const inFlight = this.inFlight.get(key);
|
|
53
|
+
if (inFlight) {
|
|
54
|
+
// A terminal can be observed again while its handoff is still awaiting the parent. Keep
|
|
55
|
+
// the existing receipt and consumer: replacing it in `pending` would enqueue a second
|
|
56
|
+
// wake as soon as the first delivery settles.
|
|
57
|
+
if (this.options.isObserved?.(record)) {
|
|
58
|
+
const observedAt = new Date().toISOString();
|
|
59
|
+
this.rememberObserved(terminalIdentity(record), observedAt);
|
|
60
|
+
inFlight.record.observedAt = observedAt;
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const identity = terminalIdentity(record);
|
|
65
|
+
const observedAt = this.options.isObserved?.(record)
|
|
66
|
+
? new Date().toISOString()
|
|
67
|
+
: this.observedTerminals.get(identity);
|
|
68
|
+
if (observedAt)
|
|
69
|
+
this.rememberObserved(identity, observedAt);
|
|
46
70
|
this.pending.set(key, {
|
|
47
71
|
key,
|
|
48
72
|
record: {
|
|
49
73
|
laneId: record.laneId,
|
|
50
74
|
status: record.status,
|
|
75
|
+
...(record.completedAt ? { completedAt: record.completedAt } : {}),
|
|
51
76
|
...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),
|
|
52
77
|
...(record.goalId ? { goalId: record.goalId } : {}),
|
|
78
|
+
...(observedAt ? { observedAt } : {}),
|
|
53
79
|
},
|
|
54
80
|
...(durableNotificationId ? { durableNotificationId } : {}),
|
|
55
81
|
});
|
|
56
82
|
this.schedule();
|
|
57
83
|
}
|
|
84
|
+
/** Mark exact terminal generations as already exposed to the parent model. */
|
|
85
|
+
observeTerminals(records, observedAt = new Date().toISOString()) {
|
|
86
|
+
const identities = new Set(records.map(terminalIdentity));
|
|
87
|
+
for (const identity of identities)
|
|
88
|
+
this.rememberObserved(identity, observedAt);
|
|
89
|
+
for (const notification of [...this.pending.values(), ...this.inFlight.values()]) {
|
|
90
|
+
if (identities.has(terminalIdentity(notification.record)))
|
|
91
|
+
notification.record.observedAt = observedAt;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
rememberObserved(identity, observedAt) {
|
|
95
|
+
this.observedTerminals.delete(identity);
|
|
96
|
+
this.observedTerminals.set(identity, observedAt);
|
|
97
|
+
while (this.observedTerminals.size > MAX_OBSERVED_TERMINALS) {
|
|
98
|
+
const oldest = this.observedTerminals.keys().next().value;
|
|
99
|
+
if (oldest === undefined)
|
|
100
|
+
break;
|
|
101
|
+
this.observedTerminals.delete(oldest);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
58
104
|
statusChanged() {
|
|
59
105
|
this.schedule();
|
|
60
106
|
}
|
|
@@ -65,8 +111,12 @@ export class WorkerNotificationCoordinator {
|
|
|
65
111
|
if (this.retryTimer)
|
|
66
112
|
clearTimeout(this.retryTimer);
|
|
67
113
|
this.retryTimer = undefined;
|
|
114
|
+
for (const watchdog of this.handoffWatchdogs)
|
|
115
|
+
clearTimeout(watchdog);
|
|
116
|
+
this.handoffWatchdogs.clear();
|
|
68
117
|
this.pending.clear();
|
|
69
118
|
this.inFlight.clear();
|
|
119
|
+
this.observedTerminals.clear();
|
|
70
120
|
}
|
|
71
121
|
schedule() {
|
|
72
122
|
if (this.disposed || this.scheduled)
|
|
@@ -104,11 +154,18 @@ export class WorkerNotificationCoordinator {
|
|
|
104
154
|
*/
|
|
105
155
|
startHandoffWatchdog(laneIds) {
|
|
106
156
|
const timer = setTimeout(() => {
|
|
157
|
+
this.handoffWatchdogs.delete(timer);
|
|
107
158
|
this.warnBestEffort(`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(", ")}. Observation only; no redispatch will occur.`);
|
|
108
159
|
}, HANDOFF_WATCHDOG_MS);
|
|
160
|
+
this.handoffWatchdogs.add(timer);
|
|
109
161
|
if (typeof timer === "object" && "unref" in timer)
|
|
110
162
|
timer.unref();
|
|
111
|
-
return {
|
|
163
|
+
return {
|
|
164
|
+
clear: () => {
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
this.handoffWatchdogs.delete(timer);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
112
169
|
}
|
|
113
170
|
flush() {
|
|
114
171
|
this.scheduled = false;
|
|
@@ -167,8 +224,17 @@ export class WorkerNotificationCoordinator {
|
|
|
167
224
|
this.inFlight.delete(notification.key);
|
|
168
225
|
this.retryCount = 0;
|
|
169
226
|
const durableIds = batch.flatMap((notification) => notification.durableNotificationId ? [notification.durableNotificationId] : []);
|
|
170
|
-
if (durableIds.length > 0)
|
|
171
|
-
|
|
227
|
+
if (durableIds.length > 0) {
|
|
228
|
+
try {
|
|
229
|
+
this.options.markDurableDelivered(durableIds);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
// Delivery is already confirmed. Retrying notify() would wake the parent twice just
|
|
233
|
+
// to repair a separate durable acknowledgment; keep the ledger pending for a future
|
|
234
|
+
// replay and make the acknowledgment failure observable instead.
|
|
235
|
+
this.warnBestEffort(`Background worker durable handoff acknowledgment failed after delivery: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
172
238
|
});
|
|
173
239
|
this.deliveryTail = delivery.catch((error) => {
|
|
174
240
|
for (const notification of batch) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-notification-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LaneRecord, LaneTerminalStatus } from \"../autonomy/lane-tracker.ts\";\n\nconst FAILED_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"failed\", \"timeout\", \"budget_exhausted\"]);\n/**\n * \"partial\", \"blocked\", and \"canceled\" are neither an outright infra failure nor a clean success —\n * each needs the parent's attention (review a partial/blocked claim, or simply note an explicit\n * stop), but folding them into `failedSinceFlush` would misclassify them as harness failures (the\n * exact bug 78a2158dd fixed in the other direction). Leaving them out of every tally instead made\n * them invisible: a blocked worker previously reported completedSinceFlush:0, failedSinceFlush:0 —\n * counted nowhere. Every LaneTerminalStatus must land in exactly one of the three tallies below.\n */\nconst ATTENTION_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"partial\", \"blocked\", \"canceled\"]);\n\n/**\n * Reuses the former handoff-timeout boundary, now purely as an observation threshold: a re-dispatch\n * on this timer used to create a duplicate consumer of the same handoff, so it was removed. Without\n * any signal in its place, a notify() call that never settles would block deliveryTail (and every\n * subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.\n */\nconst HANDOFF_WATCHDOG_MS = 1_800_000;\n\nexport interface WorkerTerminalHandoffRecord {\n\tlaneId: string;\n\tstatus: LaneTerminalStatus;\n\treasonCode?: string;\n\t/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */\n\tgoalId?: string;\n}\n\nexport interface WorkerNotificationStatus {\n\tactive: number;\n\tqueued: number;\n\trunning: number;\n\tcompletedSinceFlush: number;\n\tfailedSinceFlush: number;\n\t/** partial, blocked, and canceled terminals — needs parent review, not a harness failure. */\n\tattentionSinceFlush: number;\n\tterminalSinceFlush: readonly WorkerTerminalHandoffRecord[];\n}\n\ninterface PendingWorkerNotification {\n\tkey: string;\n\trecord: WorkerTerminalHandoffRecord;\n\tdurableNotificationId?: string;\n}\n\nexport interface WorkerNotificationCoordinatorOptions {\n\tgetWorkerRecords(): readonly LaneRecord[];\n\temitStatus(status: WorkerNotificationStatus): void;\n\tnotify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;\n\twarn(message: string): void;\n\tmarkDurableDelivered(notificationIds: readonly string[]): void;\n}\n\n/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */\nexport class WorkerNotificationCoordinator {\n\tprivate readonly options: WorkerNotificationCoordinatorOptions;\n\tprivate readonly pending = new Map<string, PendingWorkerNotification>();\n\t/**\n\t * Notifications currently being attempted by notify() — moved here from `pending` the instant\n\t * delivery starts, never cleared until notify() is CONFIRMED to have settled (success or\n\t * failure). If notify() never settles, this remains the durable, externally-visible record of\n\t * what's stuck: a batch must never be reachable ONLY through the one promise closure that may\n\t * never resolve (that closure is what previously starved every worker queued behind it, with\n\t * no trace of the lost batch anywhere). getOutstandingRecords() exposes `pending ∪ inFlight` so\n\t * an owning caller can durably persist and replay them across a process restart.\n\t */\n\tprivate readonly inFlight = new Map<string, PendingWorkerNotification>();\n\tprivate scheduled = false;\n\tprivate disposed = false;\n\tprivate deliveryTail = Promise.resolve();\n\tprivate retryTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate retryCount = 0;\n\n\tconstructor(options: WorkerNotificationCoordinatorOptions) {\n\t\tthis.options = options;\n\t}\n\n\t/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */\n\tgetOutstandingRecords(): readonly WorkerTerminalHandoffRecord[] {\n\t\treturn [...this.pending.values(), ...this.inFlight.values()].map((notification) => notification.record);\n\t}\n\n\trecordTerminal(record: LaneRecord, durableNotificationId?: string): void {\n\t\tif (record.status === \"queued\" || record.status === \"running\") return;\n\t\tconst key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;\n\t\tthis.pending.set(key, {\n\t\t\tkey,\n\t\t\trecord: {\n\t\t\t\tlaneId: record.laneId,\n\t\t\t\tstatus: record.status,\n\t\t\t\t...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),\n\t\t\t\t...(record.goalId ? { goalId: record.goalId } : {}),\n\t\t\t},\n\t\t\t...(durableNotificationId ? { durableNotificationId } : {}),\n\t\t});\n\t\tthis.schedule();\n\t}\n\n\tstatusChanged(): void {\n\t\tthis.schedule();\n\t}\n\n\t/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.scheduled = false;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.pending.clear();\n\t\tthis.inFlight.clear();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.scheduled) return;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.scheduled = true;\n\t\tqueueMicrotask(() => this.flush());\n\t}\n\n\tprivate scheduleRetry(): void {\n\t\tif (this.disposed || this.scheduled || this.retryTimer) return;\n\t\tconst delayMs = Math.min(100 * 2 ** Math.min(this.retryCount, 5), 5_000);\n\t\tthis.retryCount++;\n\t\tthis.retryTimer = setTimeout(() => {\n\t\t\tthis.retryTimer = undefined;\n\t\t\tthis.schedule();\n\t\t}, delayMs);\n\t\tif (typeof this.retryTimer === \"object\" && \"unref\" in this.retryTimer) this.retryTimer.unref();\n\t}\n\n\tprivate warnBestEffort(message: string): void {\n\t\ttry {\n\t\t\tthis.options.warn(message);\n\t\t} catch {\n\t\t\t// Diagnostics cannot consume or stop durable notification delivery.\n\t\t}\n\t}\n\n\t/**\n\t * Observe-only: warns once if the in-flight notify() call has not settled after\n\t * HANDOFF_WATCHDOG_MS. Never re-dispatches and never creates a second notify() consumer —\n\t * callers must clear() it once the awaited notify() settles, success or failure.\n\t */\n\tprivate startHandoffWatchdog(laneIds: readonly string[]): { clear(): void } {\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(\", \")}. Observation only; no redispatch will occur.`,\n\t\t\t);\n\t\t}, HANDOFF_WATCHDOG_MS);\n\t\tif (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\t\treturn { clear: () => clearTimeout(timer) };\n\t}\n\n\tprivate flush(): void {\n\t\tthis.scheduled = false;\n\t\tif (this.disposed) return;\n\t\tconst batch = [...this.pending.values()];\n\t\tthis.pending.clear();\n\t\tlet workerRecords: readonly LaneRecord[] = [];\n\t\ttry {\n\t\t\tworkerRecords = this.options.getWorkerRecords();\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status projection failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tconst queued = workerRecords.filter((record) => record.status === \"queued\").length;\n\t\tconst running = workerRecords.filter((record) => record.status === \"running\").length;\n\t\tconst terminalSinceFlush = batch.map((notification) => notification.record);\n\t\tconst status = {\n\t\t\tactive: queued + running,\n\t\t\tqueued,\n\t\t\trunning,\n\t\t\tcompletedSinceFlush: terminalSinceFlush.filter((record) => record.status === \"succeeded\").length,\n\t\t\tfailedSinceFlush: terminalSinceFlush.filter((record) => FAILED_TERMINAL_STATUSES.has(record.status)).length,\n\t\t\tattentionSinceFlush: terminalSinceFlush.filter((record) => ATTENTION_TERMINAL_STATUSES.has(record.status))\n\t\t\t\t.length,\n\t\t\tterminalSinceFlush,\n\t\t};\n\t\ttry {\n\t\t\tthis.options.emitStatus(status);\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status observer failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tif (batch.length === 0) return;\n\t\t// Moved into `inFlight`, not merely captured by the closure below: if notify() never\n\t\t// settles, this batch stays durably visible via getOutstandingRecords() instead of being\n\t\t// reachable ONLY through this one promise, which is exactly what previously starved every\n\t\t// worker queued behind it with no trace of the lost batch anywhere.\n\t\tfor (const notification of batch) this.inFlight.set(notification.key, notification);\n\t\tconst delivery = this.deliveryTail.then(async () => {\n\t\t\tif (this.disposed) return;\n\t\t\t// A foreground lease wait is an in-flight side effect, not a failed attempt. Re-dispatching it\n\t\t\t// on a wall-clock timer creates concurrent consumers that later persist the same handoff.\n\t\t\t// Explicit rejection remains retryable; process restart replays the durable pending record.\n\t\t\tconst watchdog = this.startHandoffWatchdog(terminalSinceFlush.map((record) => record.laneId));\n\t\t\ttry {\n\t\t\t\tawait this.options.notify(terminalSinceFlush);\n\t\t\t} finally {\n\t\t\t\twatchdog.clear();\n\t\t\t}\n\t\t\tfor (const notification of batch) this.inFlight.delete(notification.key);\n\t\t\tthis.retryCount = 0;\n\t\t\tconst durableIds = batch.flatMap((notification) =>\n\t\t\t\tnotification.durableNotificationId ? [notification.durableNotificationId] : [],\n\t\t\t);\n\t\t\tif (durableIds.length > 0) this.options.markDurableDelivered(durableIds);\n\t\t});\n\t\tthis.deliveryTail = delivery.catch((error: unknown) => {\n\t\t\tfor (const notification of batch) {\n\t\t\t\tthis.inFlight.delete(notification.key);\n\t\t\t\tthis.pending.set(notification.key, notification);\n\t\t\t}\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthis.scheduleRetry();\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-notification-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LaneRecord, LaneTerminalStatus } from \"../autonomy/lane-tracker.ts\";\n\nconst FAILED_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"failed\", \"timeout\", \"budget_exhausted\"]);\n/**\n * \"partial\", \"blocked\", and \"canceled\" are neither an outright infra failure nor a clean success —\n * each needs the parent's attention (review a partial/blocked claim, or simply note an explicit\n * stop), but folding them into `failedSinceFlush` would misclassify them as harness failures (the\n * exact bug 78a2158dd fixed in the other direction). Leaving them out of every tally instead made\n * them invisible: a blocked worker previously reported completedSinceFlush:0, failedSinceFlush:0 —\n * counted nowhere. Every LaneTerminalStatus must land in exactly one of the three tallies below.\n */\nconst ATTENTION_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"partial\", \"blocked\", \"canceled\"]);\n\n/**\n * Reuses the former handoff-timeout boundary, now purely as an observation threshold: a re-dispatch\n * on this timer used to create a duplicate consumer of the same handoff, so it was removed. Without\n * any signal in its place, a notify() call that never settles would block deliveryTail (and every\n * subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.\n */\nconst HANDOFF_WATCHDOG_MS = 1_800_000;\nconst MAX_OBSERVED_TERMINALS = 512;\n\nexport interface WorkerTerminalHandoffRecord {\n\tlaneId: string;\n\tstatus: LaneTerminalStatus;\n\tcompletedAt?: string;\n\treasonCode?: string;\n\t/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */\n\tgoalId?: string;\n\t/** Runtime-only receipt. Observation consumes delivery, never mutation review. */\n\tobservedAt?: string;\n}\n\nexport interface WorkerNotificationStatus {\n\tactive: number;\n\tqueued: number;\n\trunning: number;\n\tcompletedSinceFlush: number;\n\tfailedSinceFlush: number;\n\t/** partial, blocked, and canceled terminals — needs parent review, not a harness failure. */\n\tattentionSinceFlush: number;\n\tterminalSinceFlush: readonly WorkerTerminalHandoffRecord[];\n}\n\ninterface PendingWorkerNotification {\n\tkey: string;\n\trecord: WorkerTerminalHandoffRecord;\n\tdurableNotificationId?: string;\n}\n\nexport interface WorkerNotificationCoordinatorOptions {\n\tgetWorkerRecords(): readonly LaneRecord[];\n\temitStatus(status: WorkerNotificationStatus): void;\n\tnotify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;\n\twarn(message: string): void;\n\tmarkDurableDelivered(notificationIds: readonly string[]): void;\n\t/** Active event-driven waits consume matching terminals before a second foreground wake is admitted. */\n\tisObserved?(record: LaneRecord): boolean;\n}\n\nfunction terminalIdentity(record: Pick<LaneRecord, \"laneId\" | \"status\" | \"completedAt\" | \"reasonCode\">): string {\n\treturn [record.laneId, record.completedAt ?? \"\", record.status, record.reasonCode ?? \"\"].join(\"\\0\");\n}\n\n/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */\nexport class WorkerNotificationCoordinator {\n\tprivate readonly options: WorkerNotificationCoordinatorOptions;\n\tprivate readonly pending = new Map<string, PendingWorkerNotification>();\n\t/**\n\t * Notifications currently being attempted by notify() — moved here from `pending` the instant\n\t * delivery starts, never cleared until notify() is CONFIRMED to have settled (success or\n\t * failure). If notify() never settles, this remains the durable, externally-visible record of\n\t * what's stuck: a batch must never be reachable ONLY through the one promise closure that may\n\t * never resolve (that closure is what previously starved every worker queued behind it, with\n\t * no trace of the lost batch anywhere). getOutstandingRecords() exposes `pending ∪ inFlight` so\n\t * an owning caller can durably persist and replay them across a process restart.\n\t */\n\tprivate readonly inFlight = new Map<string, PendingWorkerNotification>();\n\tprivate readonly observedTerminals = new Map<string, string>();\n\tprivate scheduled = false;\n\tprivate disposed = false;\n\tprivate deliveryTail = Promise.resolve();\n\tprivate retryTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate readonly handoffWatchdogs = new Set<ReturnType<typeof setTimeout>>();\n\tprivate retryCount = 0;\n\n\tconstructor(options: WorkerNotificationCoordinatorOptions) {\n\t\tthis.options = options;\n\t}\n\n\t/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */\n\tgetOutstandingRecords(): readonly WorkerTerminalHandoffRecord[] {\n\t\treturn [...this.pending.values(), ...this.inFlight.values()].map((notification) => notification.record);\n\t}\n\n\trecordTerminal(record: LaneRecord, durableNotificationId?: string): void {\n\t\tif (record.status === \"queued\" || record.status === \"running\") return;\n\t\tconst key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;\n\t\tconst inFlight = this.inFlight.get(key);\n\t\tif (inFlight) {\n\t\t\t// A terminal can be observed again while its handoff is still awaiting the parent. Keep\n\t\t\t// the existing receipt and consumer: replacing it in `pending` would enqueue a second\n\t\t\t// wake as soon as the first delivery settles.\n\t\t\tif (this.options.isObserved?.(record)) {\n\t\t\t\tconst observedAt = new Date().toISOString();\n\t\t\t\tthis.rememberObserved(terminalIdentity(record), observedAt);\n\t\t\t\tinFlight.record.observedAt = observedAt;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst identity = terminalIdentity(record);\n\t\tconst observedAt = this.options.isObserved?.(record)\n\t\t\t? new Date().toISOString()\n\t\t\t: this.observedTerminals.get(identity);\n\t\tif (observedAt) this.rememberObserved(identity, observedAt);\n\t\tthis.pending.set(key, {\n\t\t\tkey,\n\t\t\trecord: {\n\t\t\t\tlaneId: record.laneId,\n\t\t\t\tstatus: record.status,\n\t\t\t\t...(record.completedAt ? { completedAt: record.completedAt } : {}),\n\t\t\t\t...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),\n\t\t\t\t...(record.goalId ? { goalId: record.goalId } : {}),\n\t\t\t\t...(observedAt ? { observedAt } : {}),\n\t\t\t},\n\t\t\t...(durableNotificationId ? { durableNotificationId } : {}),\n\t\t});\n\t\tthis.schedule();\n\t}\n\n\t/** Mark exact terminal generations as already exposed to the parent model. */\n\tobserveTerminals(\n\t\trecords: readonly Pick<LaneRecord, \"laneId\" | \"status\" | \"completedAt\" | \"reasonCode\">[],\n\t\tobservedAt = new Date().toISOString(),\n\t): void {\n\t\tconst identities = new Set(records.map(terminalIdentity));\n\t\tfor (const identity of identities) this.rememberObserved(identity, observedAt);\n\t\tfor (const notification of [...this.pending.values(), ...this.inFlight.values()]) {\n\t\t\tif (identities.has(terminalIdentity(notification.record))) notification.record.observedAt = observedAt;\n\t\t}\n\t}\n\n\tprivate rememberObserved(identity: string, observedAt: string): void {\n\t\tthis.observedTerminals.delete(identity);\n\t\tthis.observedTerminals.set(identity, observedAt);\n\t\twhile (this.observedTerminals.size > MAX_OBSERVED_TERMINALS) {\n\t\t\tconst oldest = this.observedTerminals.keys().next().value;\n\t\t\tif (oldest === undefined) break;\n\t\t\tthis.observedTerminals.delete(oldest);\n\t\t}\n\t}\n\n\tstatusChanged(): void {\n\t\tthis.schedule();\n\t}\n\n\t/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.scheduled = false;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tfor (const watchdog of this.handoffWatchdogs) clearTimeout(watchdog);\n\t\tthis.handoffWatchdogs.clear();\n\t\tthis.pending.clear();\n\t\tthis.inFlight.clear();\n\t\tthis.observedTerminals.clear();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.scheduled) return;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.scheduled = true;\n\t\tqueueMicrotask(() => this.flush());\n\t}\n\n\tprivate scheduleRetry(): void {\n\t\tif (this.disposed || this.scheduled || this.retryTimer) return;\n\t\tconst delayMs = Math.min(100 * 2 ** Math.min(this.retryCount, 5), 5_000);\n\t\tthis.retryCount++;\n\t\tthis.retryTimer = setTimeout(() => {\n\t\t\tthis.retryTimer = undefined;\n\t\t\tthis.schedule();\n\t\t}, delayMs);\n\t\tif (typeof this.retryTimer === \"object\" && \"unref\" in this.retryTimer) this.retryTimer.unref();\n\t}\n\n\tprivate warnBestEffort(message: string): void {\n\t\ttry {\n\t\t\tthis.options.warn(message);\n\t\t} catch {\n\t\t\t// Diagnostics cannot consume or stop durable notification delivery.\n\t\t}\n\t}\n\n\t/**\n\t * Observe-only: warns once if the in-flight notify() call has not settled after\n\t * HANDOFF_WATCHDOG_MS. Never re-dispatches and never creates a second notify() consumer —\n\t * callers must clear() it once the awaited notify() settles, success or failure.\n\t */\n\tprivate startHandoffWatchdog(laneIds: readonly string[]): { clear(): void } {\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.handoffWatchdogs.delete(timer);\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(\", \")}. Observation only; no redispatch will occur.`,\n\t\t\t);\n\t\t}, HANDOFF_WATCHDOG_MS);\n\t\tthis.handoffWatchdogs.add(timer);\n\t\tif (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\t\treturn {\n\t\t\tclear: () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.handoffWatchdogs.delete(timer);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate flush(): void {\n\t\tthis.scheduled = false;\n\t\tif (this.disposed) return;\n\t\tconst batch = [...this.pending.values()];\n\t\tthis.pending.clear();\n\t\tlet workerRecords: readonly LaneRecord[] = [];\n\t\ttry {\n\t\t\tworkerRecords = this.options.getWorkerRecords();\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status projection failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tconst queued = workerRecords.filter((record) => record.status === \"queued\").length;\n\t\tconst running = workerRecords.filter((record) => record.status === \"running\").length;\n\t\tconst terminalSinceFlush = batch.map((notification) => notification.record);\n\t\tconst status = {\n\t\t\tactive: queued + running,\n\t\t\tqueued,\n\t\t\trunning,\n\t\t\tcompletedSinceFlush: terminalSinceFlush.filter((record) => record.status === \"succeeded\").length,\n\t\t\tfailedSinceFlush: terminalSinceFlush.filter((record) => FAILED_TERMINAL_STATUSES.has(record.status)).length,\n\t\t\tattentionSinceFlush: terminalSinceFlush.filter((record) => ATTENTION_TERMINAL_STATUSES.has(record.status))\n\t\t\t\t.length,\n\t\t\tterminalSinceFlush,\n\t\t};\n\t\ttry {\n\t\t\tthis.options.emitStatus(status);\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status observer failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tif (batch.length === 0) return;\n\t\t// Moved into `inFlight`, not merely captured by the closure below: if notify() never\n\t\t// settles, this batch stays durably visible via getOutstandingRecords() instead of being\n\t\t// reachable ONLY through this one promise, which is exactly what previously starved every\n\t\t// worker queued behind it with no trace of the lost batch anywhere.\n\t\tfor (const notification of batch) this.inFlight.set(notification.key, notification);\n\t\tconst delivery = this.deliveryTail.then(async () => {\n\t\t\tif (this.disposed) return;\n\t\t\t// A foreground lease wait is an in-flight side effect, not a failed attempt. Re-dispatching it\n\t\t\t// on a wall-clock timer creates concurrent consumers that later persist the same handoff.\n\t\t\t// Explicit rejection remains retryable; process restart replays the durable pending record.\n\t\t\tconst watchdog = this.startHandoffWatchdog(terminalSinceFlush.map((record) => record.laneId));\n\t\t\ttry {\n\t\t\t\tawait this.options.notify(terminalSinceFlush);\n\t\t\t} finally {\n\t\t\t\twatchdog.clear();\n\t\t\t}\n\t\t\tfor (const notification of batch) this.inFlight.delete(notification.key);\n\t\t\tthis.retryCount = 0;\n\t\t\tconst durableIds = batch.flatMap((notification) =>\n\t\t\t\tnotification.durableNotificationId ? [notification.durableNotificationId] : [],\n\t\t\t);\n\t\t\tif (durableIds.length > 0) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.options.markDurableDelivered(durableIds);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Delivery is already confirmed. Retrying notify() would wake the parent twice just\n\t\t\t\t\t// to repair a separate durable acknowledgment; keep the ledger pending for a future\n\t\t\t\t\t// replay and make the acknowledgment failure observable instead.\n\t\t\t\t\tthis.warnBestEffort(\n\t\t\t\t\t\t`Background worker durable handoff acknowledgment failed after delivery: ${\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t\t}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.deliveryTail = delivery.catch((error: unknown) => {\n\t\t\tfor (const notification of batch) {\n\t\t\t\tthis.inFlight.delete(notification.key);\n\t\t\t\tthis.pending.set(notification.key, notification);\n\t\t\t}\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthis.scheduleRetry();\n\t\t});\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-recovery-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-recovery-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAc,MAAM,+BAA+B,CAAC;AACvH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG1F,MAAM,MAAM,4BAA4B,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtG,MAAM,MAAM,yBAAyB,GAClC;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAUxC,MAAM,WAAW,gCAAgC;IAChD,SAAS,EAAE,eAAe,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,0BAA0B,CAAC,CAAC,CAAC;IACpE,wBAAwB,IAAI,IAAI,CAAC;IACjC,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAChD,sBAAsB,CAAC,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAAC;IAC9D,oBAAoB,CACnB,QAAQ,EAAE,OAAO,CAAC,2BAA2B,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,GACpE,4BAA4B,CAAC;IAChC,8BAA8B,IAAI,IAAI,CAAC;IACvC,yBAAyB,IAAI,IAAI,CAAC;IAClC,kFAAkF;IAClF,UAAU,CAAC,IAAI,IAAI,CAAC;IACpB,GAAG,CAAC,IAAI,MAAM,CAAC;IACf,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAcD;;;;GAIG;AACH,qBAAa,yBAAyB;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAA6B;IAC1E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;IACvE,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA2B;IAEpE,YAAY,OAAO,EAAE,gCAAgC,EAQpD;IAED,6FAA6F;IAC7F,OAAO,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"worker-recovery-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-recovery-coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -111,7 +111,12 @@ export class WorkerRecoveryCoordinator {
|
|
|
111
111
|
this.verificationRecoveryFailures.set(recovery.subjectTaskId, started.skipReason);
|
|
112
112
|
this.options.warn(`Recovered verification for ${recovery.subjectTaskId} did not start: ${started.skipReason}`);
|
|
113
113
|
}
|
|
114
|
-
const terminalRecords = lifecycle
|
|
114
|
+
const terminalRecords = lifecycle
|
|
115
|
+
.getPendingTerminalNotifications()
|
|
116
|
+
.map((notification) => notification.record)
|
|
117
|
+
// ManagedLaneController owns tmux projection and durable delivery; replaying it here
|
|
118
|
+
// creates a second publisher every time unrelated foreground state triggers recovery.
|
|
119
|
+
.filter((record) => record.type !== "tmux-worker");
|
|
115
120
|
if (terminalRecords.length > 0) {
|
|
116
121
|
if (this.options.publishTerminalRecords)
|
|
117
122
|
this.options.publishTerminalRecords(terminalRecords);
|