@provos/ironcurtain 0.11.0 → 0.12.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/README.md +9 -7
- package/dist/cli-help.d.ts +12 -0
- package/dist/cli-help.js +21 -0
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.js +8 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/agent-model-guard.d.ts +14 -0
- package/dist/config/agent-model-guard.js +24 -0
- package/dist/config/agent-model-guard.js.map +1 -0
- package/dist/config/config-command.js +116 -1
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/first-start.js +2 -8
- package/dist/config/first-start.js.map +1 -1
- package/dist/config/model-provider.d.ts +9 -0
- package/dist/config/model-provider.js +13 -0
- package/dist/config/model-provider.js.map +1 -1
- package/dist/config/paths.d.ts +48 -6
- package/dist/config/paths.js +63 -8
- package/dist/config/paths.js.map +1 -1
- package/dist/config/user-config.d.ts +48 -1
- package/dist/config/user-config.js +49 -1
- package/dist/config/user-config.js.map +1 -1
- package/dist/daemon/daemon-command.js +14 -5
- package/dist/daemon/daemon-command.js.map +1 -1
- package/dist/daemon/ironcurtain-daemon.d.ts +18 -0
- package/dist/daemon/ironcurtain-daemon.js +22 -1
- package/dist/daemon/ironcurtain-daemon.js.map +1 -1
- package/dist/daemon-client/daemon-client.d.ts +123 -0
- package/dist/daemon-client/daemon-client.js +324 -0
- package/dist/daemon-client/daemon-client.js.map +1 -0
- package/dist/docker/adapters/codex.d.ts +9 -0
- package/dist/docker/adapters/codex.js +297 -0
- package/dist/docker/adapters/codex.js.map +1 -0
- package/dist/docker/agent-adapter.d.ts +5 -1
- package/dist/docker/agent-adapter.js +2 -0
- package/dist/docker/agent-adapter.js.map +1 -1
- package/dist/docker/agent-registry.js +5 -0
- package/dist/docker/agent-registry.js.map +1 -1
- package/dist/docker/apple-container-manager.d.ts +49 -0
- package/dist/docker/apple-container-manager.js +464 -0
- package/dist/docker/apple-container-manager.js.map +1 -0
- package/dist/docker/code-mode-proxy.d.ts +11 -0
- package/dist/docker/code-mode-proxy.js +3 -1
- package/dist/docker/code-mode-proxy.js.map +1 -1
- package/dist/docker/container-lifecycle.d.ts +2 -2
- package/dist/docker/container-lifecycle.js.map +1 -1
- package/dist/docker/container-runtime.d.ts +29 -0
- package/dist/docker/container-runtime.js +76 -0
- package/dist/docker/container-runtime.js.map +1 -0
- package/dist/docker/docker-agent-session.js +30 -1
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +186 -9
- package/dist/docker/docker-infrastructure.js +521 -77
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +25 -5
- package/dist/docker/docker-manager.js +262 -22
- package/dist/docker/docker-manager.js.map +1 -1
- package/dist/docker/docker-probe.d.ts +45 -0
- package/dist/docker/docker-probe.js +86 -0
- package/dist/docker/docker-probe.js.map +1 -0
- package/dist/docker/docker-progress-sink.d.ts +1 -1
- package/dist/docker/mitm-proxy.d.ts +52 -1
- package/dist/docker/mitm-proxy.js +234 -10
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/network-topology.d.ts +81 -0
- package/dist/docker/network-topology.js +160 -0
- package/dist/docker/network-topology.js.map +1 -0
- package/dist/docker/oauth-credentials.d.ts +13 -0
- package/dist/docker/oauth-credentials.js +125 -0
- package/dist/docker/oauth-credentials.js.map +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/provider-config.d.ts +29 -1
- package/dist/docker/provider-config.js +93 -3
- package/dist/docker/provider-config.js.map +1 -1
- package/dist/docker/provision-lock.d.ts +46 -0
- package/dist/docker/provision-lock.js +152 -0
- package/dist/docker/provision-lock.js.map +1 -0
- package/dist/docker/pty-session.d.ts +15 -0
- package/dist/docker/pty-session.js +139 -67
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/docker/registry-proxy.d.ts +46 -0
- package/dist/docker/registry-proxy.js +255 -1
- package/dist/docker/registry-proxy.js.map +1 -1
- package/dist/docker/resource-limits.d.ts +14 -5
- package/dist/docker/resource-limits.js +11 -8
- package/dist/docker/resource-limits.js.map +1 -1
- package/dist/docker/trajectory-capture.d.ts +79 -0
- package/dist/docker/trajectory-capture.js +521 -0
- package/dist/docker/trajectory-capture.js.map +1 -0
- package/dist/docker/trajectory-reassembler.d.ts +286 -0
- package/dist/docker/trajectory-reassembler.js +990 -0
- package/dist/docker/trajectory-reassembler.js.map +1 -0
- package/dist/docker/trajectory-tap.d.ts +100 -0
- package/dist/docker/trajectory-tap.js +410 -0
- package/dist/docker/trajectory-tap.js.map +1 -0
- package/dist/docker/trajectory-types.d.ts +187 -0
- package/dist/docker/trajectory-types.js +43 -0
- package/dist/docker/trajectory-types.js.map +1 -0
- package/dist/docker/types.d.ts +53 -7
- package/dist/doctor/checks.d.ts +36 -3
- package/dist/doctor/checks.js +102 -15
- package/dist/doctor/checks.js.map +1 -1
- package/dist/doctor/doctor-command.js +39 -9
- package/dist/doctor/doctor-command.js.map +1 -1
- package/dist/doctor/mcp-liveness.d.ts +1 -1
- package/dist/doctor/mcp-liveness.js +12 -4
- package/dist/doctor/mcp-liveness.js.map +1 -1
- package/dist/index.js +30 -12
- package/dist/index.js.map +1 -1
- package/dist/mux/mux-app.d.ts +2 -0
- package/dist/mux/mux-app.js +1 -0
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.js +19 -6
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/pty-bridge.d.ts +2 -0
- package/dist/mux/pty-bridge.js +3 -0
- package/dist/mux/pty-bridge.js.map +1 -1
- package/dist/observe/observe-command.js +112 -125
- package/dist/observe/observe-command.js.map +1 -1
- package/dist/persona/broad-policy-validator.d.ts +95 -0
- package/dist/persona/broad-policy-validator.js +171 -0
- package/dist/persona/broad-policy-validator.js.map +1 -0
- package/dist/persona/compile-persona-policy.d.ts +54 -2
- package/dist/persona/compile-persona-policy.js +29 -4
- package/dist/persona/compile-persona-policy.js.map +1 -1
- package/dist/persona/event-bus-progress-reporter.d.ts +57 -0
- package/dist/persona/event-bus-progress-reporter.js +66 -0
- package/dist/persona/event-bus-progress-reporter.js.map +1 -0
- package/dist/persona/persona-command.js +46 -76
- package/dist/persona/persona-command.js.map +1 -1
- package/dist/persona/persona-compile-orchestrator.d.ts +101 -0
- package/dist/persona/persona-compile-orchestrator.js +504 -0
- package/dist/persona/persona-compile-orchestrator.js.map +1 -0
- package/dist/persona/persona-service.d.ts +137 -0
- package/dist/persona/persona-service.js +263 -0
- package/dist/persona/persona-service.js.map +1 -0
- package/dist/persona/policy-mutation-audit.d.ts +109 -0
- package/dist/persona/policy-mutation-audit.js +179 -0
- package/dist/persona/policy-mutation-audit.js.map +1 -0
- package/dist/persona/rule-delta.d.ts +30 -0
- package/dist/persona/rule-delta.js +82 -0
- package/dist/persona/rule-delta.js.map +1 -0
- package/dist/persona/types.d.ts +12 -0
- package/dist/pipeline/annotate.js +10 -2
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/compile.js +14 -2
- package/dist/pipeline/compile.js.map +1 -1
- package/dist/pipeline/pipeline-runner.d.ts +63 -4
- package/dist/pipeline/pipeline-runner.js +159 -50
- package/dist/pipeline/pipeline-runner.js.map +1 -1
- package/dist/pipeline/pipeline-shared.d.ts +32 -3
- package/dist/pipeline/pipeline-shared.js +76 -8
- package/dist/pipeline/pipeline-shared.js.map +1 -1
- package/dist/pipeline/refresh-lists.js +3 -5
- package/dist/pipeline/refresh-lists.js.map +1 -1
- package/dist/sandbox/index.d.ts +19 -4
- package/dist/sandbox/index.js +31 -18
- package/dist/sandbox/index.js.map +1 -1
- package/dist/session/index.js +10 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +1 -30
- package/dist/session/preflight.js +52 -85
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/types.d.ts +9 -0
- package/dist/signal/bot-command.js +6 -1
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/setup-signal.js +1 -1
- package/dist/signal/setup-signal.js.map +1 -1
- package/dist/signal/signal-container.d.ts +3 -3
- package/dist/signal/signal-container.js +2 -2
- package/dist/signal/signal-container.js.map +1 -1
- package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
- package/dist/trusted-process/call-circuit-breaker.js +22 -3
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
- package/dist/trusted-process/container-command.d.ts +35 -0
- package/dist/trusted-process/container-command.js +49 -0
- package/dist/trusted-process/container-command.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.js +35 -3
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/policy-engine.js +13 -2
- package/dist/trusted-process/policy-engine.js.map +1 -1
- package/dist/trusted-process/tcp-server-transport.d.ts +12 -1
- package/dist/trusted-process/tcp-server-transport.js +9 -1
- package/dist/trusted-process/tcp-server-transport.js.map +1 -1
- package/dist/trusted-process/tool-call-coordinator.d.ts +22 -8
- package/dist/trusted-process/tool-call-coordinator.js +149 -65
- package/dist/trusted-process/tool-call-coordinator.js.map +1 -1
- package/dist/trusted-process/tool-call-pipeline.d.ts +8 -0
- package/dist/trusted-process/tool-call-pipeline.js +68 -34
- package/dist/trusted-process/tool-call-pipeline.js.map +1 -1
- package/dist/util/atomic-write.d.ts +31 -0
- package/dist/util/atomic-write.js +43 -0
- package/dist/util/atomic-write.js.map +1 -0
- package/dist/web-ui/conn-registry.d.ts +14 -0
- package/dist/web-ui/conn-registry.js +25 -0
- package/dist/web-ui/conn-registry.js.map +1 -0
- package/dist/web-ui/dispatch/persona-dispatch.d.ts +46 -2
- package/dist/web-ui/dispatch/persona-dispatch.js +209 -56
- package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/session-dispatch.js +22 -4
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/types.d.ts +23 -0
- package/dist/web-ui/dispatch/types.js +4 -0
- package/dist/web-ui/dispatch/types.js.map +1 -1
- package/dist/web-ui/dispatch/workflow-dispatch.js +116 -5
- package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -1
- package/dist/web-ui/json-rpc-dispatch.js +1 -1
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
- package/dist/web-ui/web-event-bus.d.ts +25 -1
- package/dist/web-ui/web-event-bus.js.map +1 -1
- package/dist/web-ui/web-ui-server.d.ts +14 -0
- package/dist/web-ui/web-ui-server.js +16 -0
- package/dist/web-ui/web-ui-server.js.map +1 -1
- package/dist/web-ui/web-ui-types.d.ts +133 -5
- package/dist/web-ui/web-ui-types.js.map +1 -1
- package/dist/web-ui-static/assets/index-BD5U6ILh.css +1 -0
- package/dist/web-ui-static/assets/index-FMsHWEfK.js +79 -0
- package/dist/web-ui-static/index.html +2 -2
- package/dist/workflow/cli-shared.d.ts +62 -0
- package/dist/workflow/cli-shared.js +117 -0
- package/dist/workflow/cli-shared.js.map +1 -0
- package/dist/workflow/cli-support.js +0 -2
- package/dist/workflow/cli-support.js.map +1 -1
- package/dist/workflow/container-snapshots.d.ts +29 -0
- package/dist/workflow/container-snapshots.js +137 -0
- package/dist/workflow/container-snapshots.js.map +1 -0
- package/dist/workflow/daemon-gate-commands.d.ts +21 -0
- package/dist/workflow/daemon-gate-commands.js +599 -0
- package/dist/workflow/daemon-gate-commands.js.map +1 -0
- package/dist/workflow/discovery.d.ts +29 -0
- package/dist/workflow/discovery.js +67 -7
- package/dist/workflow/discovery.js.map +1 -1
- package/dist/workflow/lane-template.d.ts +89 -0
- package/dist/workflow/lane-template.js +141 -0
- package/dist/workflow/lane-template.js.map +1 -0
- package/dist/workflow/lint.d.ts +7 -1
- package/dist/workflow/lint.js +186 -3
- package/dist/workflow/lint.js.map +1 -1
- package/dist/workflow/machine-builder.d.ts +90 -2
- package/dist/workflow/machine-builder.js +222 -29
- package/dist/workflow/machine-builder.js.map +1 -1
- package/dist/workflow/message-log.d.ts +15 -1
- package/dist/workflow/message-log.js.map +1 -1
- package/dist/workflow/orchestrator.d.ts +505 -1
- package/dist/workflow/orchestrator.js +1722 -69
- package/dist/workflow/orchestrator.js.map +1 -1
- package/dist/workflow/prompt-builder.js +2 -1
- package/dist/workflow/prompt-builder.js.map +1 -1
- package/dist/workflow/run-state-command.js +1 -1
- package/dist/workflow/run-state-command.js.map +1 -1
- package/dist/workflow/status-parser.js +19 -4
- package/dist/workflow/status-parser.js.map +1 -1
- package/dist/workflow/types.d.ts +123 -23
- package/dist/workflow/types.js +2 -0
- package/dist/workflow/types.js.map +1 -1
- package/dist/workflow/validate.d.ts +23 -1
- package/dist/workflow/validate.js +311 -22
- package/dist/workflow/validate.js.map +1 -1
- package/dist/workflow/workflow-command.d.ts +0 -17
- package/dist/workflow/workflow-command.js +110 -88
- package/dist/workflow/workflow-command.js.map +1 -1
- package/dist/workflow/workflow-discovery.d.ts +2 -0
- package/dist/workflow/workflow-discovery.js +22 -1
- package/dist/workflow/workflow-discovery.js.map +1 -1
- package/dist/workflow/workflow-manager.d.ts +34 -0
- package/dist/workflow/workflow-manager.js +52 -1
- package/dist/workflow/workflow-manager.js.map +1 -1
- package/dist/workflow/workflows/design-and-code/README.md +50 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/dist/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/dist/workflow/workflows/evolve/scripts/README.md +314 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/dist/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/dist/workflow/workflows/evolve/workflow.yaml +646 -0
- package/dist/workflow/workflows/test-email-summary/workflow.yaml +1 -0
- package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/dist/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/docker/Dockerfile.base +22 -0
- package/docker/Dockerfile.base.arm64 +18 -0
- package/docker/Dockerfile.claude-code +3 -1
- package/docker/Dockerfile.codex +17 -0
- package/docker/Dockerfile.goose +3 -1
- package/docker/entrypoint-claude-code.sh +6 -45
- package/docker/entrypoint-codex.sh +42 -0
- package/docker/entrypoint-goose.sh +5 -24
- package/docker/entrypoint-uid-remap.sh +93 -0
- package/package.json +9 -4
- package/src/workflow/workflows/design-and-code/README.md +50 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/src/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/src/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/src/workflow/workflows/evolve/scripts/README.md +314 -0
- package/src/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/src/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/src/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/src/workflow/workflows/evolve/workflow.yaml +646 -0
- package/src/workflow/workflows/test-email-summary/workflow.yaml +1 -0
- package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/src/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
|
@@ -27,6 +27,7 @@ import type { ResolvedSkill } from '../skills/types.js';
|
|
|
27
27
|
* location.
|
|
28
28
|
*/
|
|
29
29
|
export declare function stageWorkflowSkillsAtStart(packageDir: string, runMetaDir: string): string | undefined;
|
|
30
|
+
export declare function stageWorkflowScriptsAtStart(packageDir: string, runMetaDir: string): string | undefined;
|
|
30
31
|
/** Handle for writing to a workflow tab in the mux. */
|
|
31
32
|
export interface WorkflowTabHandle {
|
|
32
33
|
write(text: string): void;
|
|
@@ -88,6 +89,10 @@ export interface CreateWorkflowInfrastructureInput {
|
|
|
88
89
|
* Persona skills are layered in per-state via `bundle.restageSkills`.
|
|
89
90
|
*/
|
|
90
91
|
readonly resolvedSkills?: readonly ResolvedSkill[];
|
|
92
|
+
/** Per-run staged workflow scripts directory to mount read-only in the bundle. */
|
|
93
|
+
readonly workflowScriptsDir?: string;
|
|
94
|
+
/** Optional immutable snapshot image digest to use for the main container. */
|
|
95
|
+
readonly baseImageOverride?: string;
|
|
91
96
|
}
|
|
92
97
|
/** Inputs for starting the coordinator's HTTP control server on a workflow bundle. */
|
|
93
98
|
export interface StartWorkflowControlServerInput {
|
|
@@ -157,6 +162,17 @@ export interface WorkflowOrchestratorDeps {
|
|
|
157
162
|
* to assert on the RPC shape without standing up a real socket.
|
|
158
163
|
*/
|
|
159
164
|
readonly loadPolicyRpc?: (input: LoadPolicyRpcInput) => Promise<void>;
|
|
165
|
+
/**
|
|
166
|
+
* Raw trajectory-capture override for this workflow run (CLI
|
|
167
|
+
* `--capture-traces` flag). Passed UNRESOLVED to the infrastructure
|
|
168
|
+
* factory, which is the single place that resolves it against
|
|
169
|
+
* `userConfig.capture?.enabled`. When resolution yields true, the
|
|
170
|
+
* factory constructs a writer for each bundle and `executeAgentState`
|
|
171
|
+
* brackets each agent's session with `bundle.beginCaptureSession` /
|
|
172
|
+
* `bundle.endCaptureSession`. Undefined falls through to config.
|
|
173
|
+
* See docs/designs/mitm-token-trajectory-capture.md §10.
|
|
174
|
+
*/
|
|
175
|
+
readonly captureTracesOverride?: boolean;
|
|
160
176
|
}
|
|
161
177
|
/** Lifecycle events emitted by the orchestrator. */
|
|
162
178
|
export type WorkflowLifecycleEvent = {
|
|
@@ -356,6 +372,20 @@ export declare class WorkflowOrchestrator implements WorkflowController {
|
|
|
356
372
|
* test or CLI layer), which is the intended signal.
|
|
357
373
|
*/
|
|
358
374
|
private destroyWorkflowInfrastructure;
|
|
375
|
+
/** Body of the bundle teardown; only ever started once per instance. */
|
|
376
|
+
private runBundleTeardown;
|
|
377
|
+
private shouldSnapshotOnStop;
|
|
378
|
+
private snapshotResumableScopes;
|
|
379
|
+
private dockerForSnapshotCleanup;
|
|
380
|
+
private removeSnapshotImagesAfterTeardown;
|
|
381
|
+
/**
|
|
382
|
+
* Builds and persists the terminal checkpoint, preserving the prior on-disk
|
|
383
|
+
* machineState/context (which point at the last non-terminal save point) so
|
|
384
|
+
* resume re-enters that state instead of the terminal snapshot. Shared by the
|
|
385
|
+
* abort() and handleWorkflowComplete() stop paths.
|
|
386
|
+
*/
|
|
387
|
+
private saveTerminalCheckpoint;
|
|
388
|
+
private snapshotsSupersededBy;
|
|
359
389
|
/**
|
|
360
390
|
* Lazy-loads the default `createDockerInfrastructure` wrapper. The real
|
|
361
391
|
* helper requires Docker dependencies and the session config, so we
|
|
@@ -399,7 +429,14 @@ export declare class WorkflowOrchestrator implements WorkflowController {
|
|
|
399
429
|
abort(id: WorkflowId): Promise<void>;
|
|
400
430
|
onEvent(callback: (event: WorkflowLifecycleEvent) => void): void;
|
|
401
431
|
shutdownAll(): Promise<void>;
|
|
402
|
-
/**
|
|
432
|
+
/**
|
|
433
|
+
* Injects concrete service implementations into the machine: `agentService`
|
|
434
|
+
* and `deterministicService` for executable states, plus `fanOutService` —
|
|
435
|
+
* the invoke body of a `workers` fan-out state, which runs
|
|
436
|
+
* {@link runFanOutSegment} and is re-provided onto each child round machine
|
|
437
|
+
* (the children reuse the same agent/deterministic actors, lane-scoped via
|
|
438
|
+
* input).
|
|
439
|
+
*/
|
|
403
440
|
private provideActors;
|
|
404
441
|
/** Subscribes to actor snapshot changes for lifecycle events, gates, and checkpointing. */
|
|
405
442
|
private subscribeToActor;
|
|
@@ -414,7 +451,474 @@ export declare class WorkflowOrchestrator implements WorkflowController {
|
|
|
414
451
|
private buildCheckpoint;
|
|
415
452
|
private saveCheckpoint;
|
|
416
453
|
private executeAgentState;
|
|
454
|
+
/**
|
|
455
|
+
* Runs one fan-out batch: the invoke body of the real `workers` state,
|
|
456
|
+
* registered as the `fanOutService` actor (see {@link provideActors}). For
|
|
457
|
+
* each worker it creates a free-standing child round actor, starts it, and
|
|
458
|
+
* barrier-joins on every child reaching a `final` state, then folds the lane
|
|
459
|
+
* verdicts into a single parent-edge result (§6.2).
|
|
460
|
+
*
|
|
461
|
+
* WHY free-standing `createActor` + `.start()` and NOT in-context `spawn`:
|
|
462
|
+
* this is a `fromPromise` invoke body (plain async TS), not an XState entry
|
|
463
|
+
* action — `spawn` is only callable from inside an action. A free-standing
|
|
464
|
+
* actor is its OWN root, so the parent's `snapshot.value` stays the string
|
|
465
|
+
* `"workers"` (single-active-state spine preserved, §6.4); the children's
|
|
466
|
+
* snapshots are their own, read here via {@link waitForRoundChild}. A
|
|
467
|
+
* `type:'parallel'` region would instead fold into the parent's `value` and
|
|
468
|
+
* make it an object — fatal to checkpoint/terminal/gate serialization (§6.4).
|
|
469
|
+
*
|
|
470
|
+
* WHY mint the scope bundle BEFORE fan-out: {@link preMintFanOutScopeBundle}
|
|
471
|
+
* runs `ensureBundleForScope` serially up front so the single shared
|
|
472
|
+
* container exists before any child's first `container:true` step. N children
|
|
473
|
+
* racing their first container step would each see an empty `bundlesByScope`
|
|
474
|
+
* and mint a SEPARATE container, defeating `sharedContainer` (§6.2 / §8.1;
|
|
475
|
+
* cross-ref the `ensureBundleForScope` check-then-act race comment).
|
|
476
|
+
*
|
|
477
|
+
* Never throws: every failure path — workflow gone, misconfigured segment,
|
|
478
|
+
* unsupported worker count, missing child machine — funnels through
|
|
479
|
+
* {@link fanOutErrorResult}, which yields a `result_file_error` verdict that
|
|
480
|
+
* the parent `workers` state routes to its `failed` edge. (The `fanOutService`
|
|
481
|
+
* wrapper in {@link provideActors} would also catch a thrown error, but the
|
|
482
|
+
* uniform result keeps the parent transition table verdict-driven.)
|
|
483
|
+
*/
|
|
484
|
+
private runFanOutSegment;
|
|
485
|
+
/**
|
|
486
|
+
* Promotes recorded lane lessons once, serially, at the fan-out barrier. This
|
|
487
|
+
* is the workers>1 cognition single-writer point (§9): lane `attach_analysis`
|
|
488
|
+
* calls only record durable nodes; the parent invokes `promote_cognition`
|
|
489
|
+
* after every child has recorded and before re-entering `orchestrator`.
|
|
490
|
+
*
|
|
491
|
+
* Only `recorded` lanes are promoted — blocked/errored children are filtered
|
|
492
|
+
* out because they contributed no durable node to seed a lesson from.
|
|
493
|
+
*
|
|
494
|
+
* Returns one of three shapes:
|
|
495
|
+
* - `{ error }` — the promotion ran but did not pass (the bridge returned a
|
|
496
|
+
* non-`cognition_promoted` verdict / `needs_repair`), OR — a hard error —
|
|
497
|
+
* `lanes.length === 0` for a workers>1 recorded batch (every recorded child
|
|
498
|
+
* should carry a lane id, so an empty set means the join is inconsistent).
|
|
499
|
+
* - `{ result }` — the promotion passed; the caller folds the payload into the
|
|
500
|
+
* batch result under `cognition_promotion`.
|
|
501
|
+
* - `{}` — a no-op, when {@link buildEvolvePromoteCognitionInput} returns
|
|
502
|
+
* undefined (non-evolve segment, or a segment with nothing to promote).
|
|
503
|
+
*
|
|
504
|
+
* Mixed-verdict deferral (within §9, intended): this only runs when the batch
|
|
505
|
+
* verdict is `recorded`. When a batch instead escalates/fails, recorded lanes'
|
|
506
|
+
* lessons are NOT promoted that turn — on APPROVE→resume the recorded lanes
|
|
507
|
+
* idempotent-skip then barrier-promote (the ledger dedups), but an
|
|
508
|
+
* ABORT/FORCE_REVISION never promotes them, by design: an aborted batch must
|
|
509
|
+
* not seed cognition.
|
|
510
|
+
*/
|
|
511
|
+
private promoteBarrierCognition;
|
|
512
|
+
/**
|
|
513
|
+
* Locates the segment's `attach_analysis` deterministic state and its evolve
|
|
514
|
+
* command (the segment member that carries the `evolve_result.py` path and
|
|
515
|
+
* `--run-dir`). Returns `undefined` when the segment has no such state — a
|
|
516
|
+
* non-evolve fan-out has no cognition to promote.
|
|
517
|
+
*/
|
|
518
|
+
private findEvolveAttachAnalysisState;
|
|
519
|
+
/**
|
|
520
|
+
* Derives the `promote_cognition` invoke input from the segment's already-
|
|
521
|
+
* resolved `attach_analysis` command: reuses the bridge path, `--run-dir`,
|
|
522
|
+
* container scope, and timeout; rewrites the subcommand; passes the recorded
|
|
523
|
+
* lane ids; and writes one barrier-owned result at
|
|
524
|
+
* `current/cognition_promotion.json`. Returns `undefined` when the command
|
|
525
|
+
* lacks the bridge path, a `--run-dir`, or a resolvable workspace-relative
|
|
526
|
+
* result path (the caller then treats promotion as a no-op).
|
|
527
|
+
*/
|
|
528
|
+
private buildEvolvePromoteCognitionInput;
|
|
529
|
+
/**
|
|
530
|
+
* Computes the single canonical `current/stop_signals.json` ONCE at the
|
|
531
|
+
* barrier join by running the bridge's `compute_stop_signals` subcommand over
|
|
532
|
+
* the batch-grown `nodes.json`. The bridge writes the bare canonical file
|
|
533
|
+
* atomically (temp+rename); per-lane `attach_analysis` only ever wrote
|
|
534
|
+
* lane-scoped copies, so this is the sole writer of the routing input the
|
|
535
|
+
* orchestrator reads each batch (SHOULD-FIX-1).
|
|
536
|
+
*
|
|
537
|
+
* Derived from the segment head's declared `sample` command (the only segment
|
|
538
|
+
* member guaranteed to carry the `evolve_result.py` path and `--run-dir`), so
|
|
539
|
+
* it inherits the same container scope / timeout. Returns an error string on
|
|
540
|
+
* failure (the caller folds it into a `result_file_error`), or `undefined` on
|
|
541
|
+
* success — including the benign case where the segment has no recognizable
|
|
542
|
+
* evolve sample command (a non-evolve fan-out has no stop signals to compute).
|
|
543
|
+
*/
|
|
544
|
+
private computeBarrierStopSignals;
|
|
545
|
+
/**
|
|
546
|
+
* Derives the `compute_stop_signals` invoke input from the segment head's
|
|
547
|
+
* `sample` command: reuses its `evolve_result.py` path and `--run-dir`,
|
|
548
|
+
* rewrites the subcommand to `compute_stop_signals`, and points
|
|
549
|
+
* `--result-file` at the shared `current/stop_signals_compute.json` barrier
|
|
550
|
+
* artifact. Returns `undefined` when the command lacks the bridge path, a
|
|
551
|
+
* `--run-dir`, or a resolvable workspace-relative result path.
|
|
552
|
+
*/
|
|
553
|
+
private buildEvolveStopSignalsInput;
|
|
554
|
+
/**
|
|
555
|
+
* Mints the fan-out segment's shared-container bundle ONCE, before any child
|
|
556
|
+
* actor starts (the load-bearing precondition of {@link runFanOutSegment}).
|
|
557
|
+
*
|
|
558
|
+
* The mint precondition: only when the workflow actually uses a shared
|
|
559
|
+
* container (`shouldUseSharedContainer`) AND at least one segment member runs
|
|
560
|
+
* in-container. A segment with no container members needs no bundle and
|
|
561
|
+
* returns early.
|
|
562
|
+
*
|
|
563
|
+
* `ensureBundleForScope` is an unguarded check-then-act across awaits (its own
|
|
564
|
+
* doc flags the lazy-mint race): N children each hitting their first
|
|
565
|
+
* `container:true` step would each see `bundlesByScope.get(scope)` undefined
|
|
566
|
+
* and mint a SEPARATE container. Calling it once here, serially, closes that
|
|
567
|
+
* window — every child then borrows the already-minted bundle. Cross-ref the
|
|
568
|
+
* race comment on `ensureBundleForScope`.
|
|
569
|
+
*
|
|
570
|
+
* The multi-scope throw is a guardrail, not a supported path: this slice
|
|
571
|
+
* keeps the whole segment under one `containerScope` (single-policy
|
|
572
|
+
* homogeneity, §8.2). A segment spanning >1 scope is out of slice scope and
|
|
573
|
+
* fails fast rather than minting the wrong bundle.
|
|
574
|
+
*/
|
|
575
|
+
private preMintFanOutScopeBundle;
|
|
576
|
+
private buildFanOutLaneContext;
|
|
577
|
+
/**
|
|
578
|
+
* Reconstructs an in-flight evolve fan-out batch from the durable engine DB.
|
|
579
|
+
*
|
|
580
|
+
* This intentionally does NOT use XState child persistence. The checkpoint
|
|
581
|
+
* stores `{ machineState, context }` and `resolveState()` re-enters `workers`
|
|
582
|
+
* without live child ActorRefs; free-standing child actors created in the old
|
|
583
|
+
* process are gone. First-cut crash-resume therefore treats `nodes.json` as the
|
|
584
|
+
* source of truth: a recorded `step_<batch>_lane_<k>` means lane k is already
|
|
585
|
+
* done and must be synthesized, while every missing lane is re-spawned fresh
|
|
586
|
+
* from `sample`. That fresh re-run can produce a different verdict (§11.2
|
|
587
|
+
* verdict drift), which is acceptable for node-integrity but not a promise of
|
|
588
|
+
* batch-outcome reproducibility.
|
|
589
|
+
*
|
|
590
|
+
* Cross-language seam (deliberate, NOT accidental duplication). The batch-index
|
|
591
|
+
* reuse rule below re-implements Python `_next_batch_index(run_dir, workers)`.
|
|
592
|
+
* We re-derive it here rather than consume the bridge's `sample_batch_prepared`
|
|
593
|
+
* echo because the index is needed BEFORE `sample_batch` runs: TS must know it
|
|
594
|
+
* to decide synthesize-vs-respawn per lane AND to pin `--batch-index` into the
|
|
595
|
+
* very `sample_batch` call whose output would otherwise echo it. Having the
|
|
596
|
+
* bridge be authoritative would invert that ordering. So the two derivations
|
|
597
|
+
* MUST move together — TS pins `--batch-index` whenever any lane is recorded (so
|
|
598
|
+
* the bridge cannot diverge), and recomputes the identical number when none is.
|
|
599
|
+
* Both sides cite the shared `step_<batch>_lane_<k>` format (`evolveStepName` /
|
|
600
|
+
* the Python f-string) as the contract.
|
|
601
|
+
*/
|
|
602
|
+
private reconstructFanOutBatchFromDb;
|
|
603
|
+
/**
|
|
604
|
+
* The evolve `--run-dir` for this fan-out segment's `sample` head, or
|
|
605
|
+
* `undefined` when the segment head is not a deterministic evolve sample
|
|
606
|
+
* command. `undefined` makes {@link reconstructFanOutBatchFromDb} return
|
|
607
|
+
* `unavailable`, so resume falls back to re-spawning all lanes fresh.
|
|
608
|
+
*/
|
|
609
|
+
private evolveRunDirForFanOutSegment;
|
|
610
|
+
/**
|
|
611
|
+
* Reads the engine `nodes.json` node map. Missing file ⇒ `{ entries: [] }`
|
|
612
|
+
* with NO error — a fresh batch (or a run that has not recorded any node yet)
|
|
613
|
+
* is a normal pre-crash state and must reconstruct as "nothing recorded". A
|
|
614
|
+
* read or JSON-parse failure ⇒ an `error`, which aborts the fan-out: a corrupt
|
|
615
|
+
* DB is NOT safe to treat as empty (we would re-run lanes that may already be
|
|
616
|
+
* recorded), so the missing-vs-corrupt distinction is load-bearing.
|
|
617
|
+
*/
|
|
618
|
+
private readEvolveNodes;
|
|
619
|
+
private asRecord;
|
|
620
|
+
private nodeIdFromRecord;
|
|
621
|
+
/**
|
|
622
|
+
* The node's parent lineage as a tri-state: `undefined` when the record has no
|
|
623
|
+
* `parent` array at all (omit the field from the synthesized payload — lineage
|
|
624
|
+
* unknown), `[]` for a root node (an explicit empty array — root, not omitted),
|
|
625
|
+
* and `[...ids]` for a child's parent ids. The empty-vs-undefined distinction
|
|
626
|
+
* is preserved deliberately so {@link synthesizeRecordedFanOutOutcome} can omit
|
|
627
|
+
* an unknown parent while still echoing an explicit root.
|
|
628
|
+
*/
|
|
629
|
+
private nodeParentFromRecord;
|
|
630
|
+
/**
|
|
631
|
+
* Builds the barrier outcome for a lane that already recorded before a crash.
|
|
632
|
+
* The durable node proves the lane advanced; the volatile child actor context
|
|
633
|
+
* (visit counts, token spend, in-flight state) is not recoverable without the
|
|
634
|
+
* deferred `getPersistedSnapshot()` + in-context spawn migration, so this is a
|
|
635
|
+
* minimal recorded context sufficient for join, promotion, and duplicate stats.
|
|
636
|
+
*
|
|
637
|
+
* Edge cases (the contract callers rely on):
|
|
638
|
+
* - Called ONLY for a lane the engine DB already recorded — i.e. the
|
|
639
|
+
* just-before-crash case where the node landed but the process died before
|
|
640
|
+
* the join. Every NOT-recorded lane is re-spawned instead (see the fork in
|
|
641
|
+
* {@link runFanOutSegment}).
|
|
642
|
+
* - Does NOT rebuild on-disk artifacts. The lane's `analysis.md` /
|
|
643
|
+
* `analysis_record.json` may be absent post-crash, but the durable node is
|
|
644
|
+
* authoritative, so a fabricated `lastDeterministicResult` with
|
|
645
|
+
* `{ verdict: 'recorded', idempotent_skip: true }` is sufficient — nothing
|
|
646
|
+
* downstream re-reads those files for a recorded lane.
|
|
647
|
+
* - `idempotent_skip: true` is the marker that this outcome was synthesized
|
|
648
|
+
* (vs produced by a live re-run); the returned `recorded` outcome is
|
|
649
|
+
* otherwise indistinguishable to {@link joinFanOutBatch} from a live-recorded
|
|
650
|
+
* lane, so the join, promotion, and duplicate-rate paths need no special case.
|
|
651
|
+
*/
|
|
652
|
+
private synthesizeRecordedFanOutOutcome;
|
|
653
|
+
/**
|
|
654
|
+
* Runs the ONE barrier-side `sample_batch(n=workers)` before fan-out and
|
|
655
|
+
* partitions its result into per-lane pre-computed `sample` results (keyed by
|
|
656
|
+
* lane id) that {@link executeDeterministicState} replays as each child's
|
|
657
|
+
* `sample` step.
|
|
658
|
+
*
|
|
659
|
+
* WHY one barrier-side `sample_batch(n=N)` and NOT N independent `sample()`
|
|
660
|
+
* calls: the divergence between lanes is INJECTED at sampling (§7.4). N
|
|
661
|
+
* independent `sample()` calls each reload the same `nodes.json` and, with a
|
|
662
|
+
* diversity-maintaining sampler, could draw the SAME parent into multiple
|
|
663
|
+
* lanes — collapsing the N-wide frontier into "N samples of one distribution"
|
|
664
|
+
* and producing near-duplicate candidates. A single `sample_batch` over the
|
|
665
|
+
* whole DB partitions N DISTINCT parents (one per lane) in one serialized,
|
|
666
|
+
* read-only DB touch, guaranteeing disjoint parent sets up front. The bridge
|
|
667
|
+
* uses a per-lane seed offset (`base_seed + laneId`) to decorrelate the lanes
|
|
668
|
+
* while keeping the partition reproducible, with a deterministic hash tiebreak
|
|
669
|
+
* so the assignment is stable across resume (§7.4).
|
|
670
|
+
*
|
|
671
|
+
* `workers === 1` short-circuits: the single lane uses the legacy inline
|
|
672
|
+
* `sample` step (byte-identical backward compat, gate item 1), so there is no
|
|
673
|
+
* batch to prepare. A non-deterministic or unrecognized sample state likewise
|
|
674
|
+
* returns an empty map (the child runs its own `sample`).
|
|
675
|
+
*/
|
|
676
|
+
private prepareFanOutLaneResults;
|
|
677
|
+
/**
|
|
678
|
+
* Derives the deterministic invoke input for the barrier-side `sample_batch`
|
|
679
|
+
* from the segment head's declared `sample` command: rewrites the `sample`
|
|
680
|
+
* subcommand to `sample_batch`, adds `--workers <N>`, carries over the
|
|
681
|
+
* query/top-k flags, and points `--result-file` at the shared
|
|
682
|
+
* `current/sample_batch.json` (the batch artifact is barrier-owned, not
|
|
683
|
+
* lane-scoped). Returns `undefined` (the caller then lets each child sample on
|
|
684
|
+
* its own) when the segment head is not a recognizable evolve `sample`
|
|
685
|
+
* command, has no `evolve_result.py` entry, or lacks a `--run-dir` / resolvable
|
|
686
|
+
* workspace-relative result path.
|
|
687
|
+
*/
|
|
688
|
+
private buildEvolveSampleBatchInput;
|
|
689
|
+
/**
|
|
690
|
+
* Shared skeleton for the three barrier-side `evolve_result.py` invocations
|
|
691
|
+
* (`sample_batch`, `promote_cognition`, `compute_stop_signals`). Given an
|
|
692
|
+
* already-resolved `sourceCommand` (the caller does the `state.run.find`), it
|
|
693
|
+
* locates the bridge path, carries over `--run-dir`, rewrites the subcommand,
|
|
694
|
+
* splices in the per-caller `extraArgs`, and points `--result-file` at the
|
|
695
|
+
* shared barrier artifact `current/<resultBasename>`. Returns `undefined` when
|
|
696
|
+
* the source command lacks the bridge path, a `--run-dir`, or a resolvable
|
|
697
|
+
* workspace-relative result path — the caller's documented no-op signal.
|
|
698
|
+
*/
|
|
699
|
+
private buildEvolveBarrierInput;
|
|
700
|
+
private isEvolveSampleCommand;
|
|
701
|
+
private isEvolveAttachAnalysisCommand;
|
|
702
|
+
private commandFlagValue;
|
|
703
|
+
private sampleQueryArgs;
|
|
704
|
+
private sampleTopKArgs;
|
|
705
|
+
private containerPathToWorkspaceRelative;
|
|
706
|
+
/**
|
|
707
|
+
* Barrier primitive for one lane. Returns a {@link RoundChildWaiter} (NOT a
|
|
708
|
+
* bare Promise): a two-phase handle whose `promise` resolves by EITHER of two
|
|
709
|
+
* routes, and whose `drain`/`isSettled` members let the fan-out pump stop and
|
|
710
|
+
* inspect the lane externally.
|
|
711
|
+
*
|
|
712
|
+
* The two resolution routes and the discriminator {@link joinFanOutBatch} reads:
|
|
713
|
+
* - NATURAL SETTLE — the child's own snapshot reaches a `final` state
|
|
714
|
+
* (`status === 'done'`), resolving with `recorded`/`blocked`/`errored` and
|
|
715
|
+
* `drainedBy: undefined`. A free-standing child fires no parent-visible
|
|
716
|
+
* `onDone`, so the parent watches the child's OWN snapshot (§6.2) via
|
|
717
|
+
* subscribe-until-done rather than an `xstate.done.actor` event.
|
|
718
|
+
* - DRAIN — an external `drain(trigger)` call (a peer blocked/errored) stops
|
|
719
|
+
* the actor and resolves with status `drained` and a populated `drainedBy`.
|
|
720
|
+
* `drainedBy` being set vs `undefined` is exactly how the join distinguishes
|
|
721
|
+
* a drained peer from a naturally-settled lane.
|
|
722
|
+
*
|
|
723
|
+
* `isSettled` is first-wins: whichever route fires first latches `settled`, so
|
|
724
|
+
* a lane that RECORDED before the drain reached it keeps its real `recorded`
|
|
725
|
+
* outcome (the drain is a no-op on an already-settled lane).
|
|
726
|
+
*
|
|
727
|
+
* After the child `onError` -> `errored` fix, a segment-member service
|
|
728
|
+
* rejection becomes a normal `errored` TERMINAL (status `done`, value
|
|
729
|
+
* `errored`) and resolves here; the `status === 'error'` branch is the
|
|
730
|
+
* residual safety net for an actor-level throw the `errored` terminal did not
|
|
731
|
+
* catch (e.g. an entry-action throw), which resolves as an `errored` lane so
|
|
732
|
+
* drain-on-escalation can still stop peers and the join can report the full
|
|
733
|
+
* batch.
|
|
734
|
+
*
|
|
735
|
+
* WHY a hand-rolled subscribe loop and NOT `xstate`'s `waitFor`: `waitFor`
|
|
736
|
+
* resolves only when the actor's OWN snapshot stream matches a predicate. The
|
|
737
|
+
* drain route resolves the SAME promise from OUTSIDE that stream (the pump
|
|
738
|
+
* synthesizes a `drained` outcome the instant it stops the actor, without
|
|
739
|
+
* waiting for any in-flight external service call to settle, FSM-M3). `waitFor`
|
|
740
|
+
* cannot express that external resolver, so the two-phase waiter is kept.
|
|
741
|
+
*
|
|
742
|
+
* The trailing `observe(actor.getSnapshot())` after `subscribe` guards the
|
|
743
|
+
* synchronous-settle-before-subscribe race: a child whose first state
|
|
744
|
+
* settles synchronously (e.g. a sync entry-action throw) can already be
|
|
745
|
+
* `done`/`error` by the time `.subscribe` returns, so the subscription would
|
|
746
|
+
* never deliver that final snapshot. Observing the current snapshot once,
|
|
747
|
+
* immediately, closes the lane in that case.
|
|
748
|
+
*/
|
|
749
|
+
private waitForRoundChild;
|
|
750
|
+
/**
|
|
751
|
+
* Folds the settled lane outcomes into a single parent-edge result, applying
|
|
752
|
+
* a fixed verdict precedence (worst lane wins):
|
|
753
|
+
* 1. any rejected settle -> `result_file_error` (a residual actor-level
|
|
754
|
+
* throw that did not resolve as an `errored` lane);
|
|
755
|
+
* 2. else any `blocked` lane -> `escalate` (route once to human review,
|
|
756
|
+
* with every blocked/errored lane reason aggregated);
|
|
757
|
+
* 3. else any `errored` lane -> `result_file_error` (explicit fail mapping);
|
|
758
|
+
* 4. else any `drained` lane without an issue trigger -> `result_file_error`;
|
|
759
|
+
* 5. else all `recorded` -> `recorded` (the batch advanced).
|
|
760
|
+
*
|
|
761
|
+
* WHY `Promise.allSettled` (not `Promise.all`) upstream: one lane's rejection
|
|
762
|
+
* must not abandon its N-1 in-flight peers (FSM-S5). `all` would reject on the
|
|
763
|
+
* first throw and lose the other lanes' outcomes; `allSettled` lets the join
|
|
764
|
+
* see the full batch, including parent-synthesized `drained` peer outcomes.
|
|
765
|
+
*
|
|
766
|
+
* For `workers: 1`, the recorded path still promotes the single child context
|
|
767
|
+
* exactly. For N>1, the recorded path folds lane contexts into a parent batch
|
|
768
|
+
* context: child artifacts/conversations merge, parent visit counts remain
|
|
769
|
+
* authoritative for the single-active-state spine, and total tokens fan in
|
|
770
|
+
* from the orchestrator's workflow-level token accumulator.
|
|
771
|
+
*/
|
|
772
|
+
private joinFanOutBatch;
|
|
773
|
+
/**
|
|
774
|
+
* Projects the blocked/errored lanes (the offenders) into the {@link FanOutIssue}
|
|
775
|
+
* payload that lands in the aggregated gate. Drained peers are intentionally
|
|
776
|
+
* excluded — they are the drain-first collateral, not independent issues (§ the
|
|
777
|
+
* reason list is the blocked-at-drain set, not all-would-have-blocked).
|
|
778
|
+
*/
|
|
779
|
+
private fanOutIssues;
|
|
780
|
+
/**
|
|
781
|
+
* Surfaces a one-line human-readable cause for a blocked/errored lane, with an
|
|
782
|
+
* ASYMMETRIC fallback order per status — THE footgun this method guards:
|
|
783
|
+
*
|
|
784
|
+
* - `errored` prefers `lastError` then `previousAgentOutput`: an errored lane
|
|
785
|
+
* DID trip `storeError`, so `lastError` is the populated, authoritative cause.
|
|
786
|
+
* - `blocked` prefers `previousAgentOutput` then `lastError`: a blocked lane
|
|
787
|
+
* (evaluator_blocked) never trips `storeError`, so its `lastError` is null and
|
|
788
|
+
* the real reason lives on `previousAgentOutput` (the evaluator's message).
|
|
789
|
+
*
|
|
790
|
+
* Do NOT collapse the two branches into one fallback chain: a unified order
|
|
791
|
+
* would surface a stale/null field for one of the two statuses. This rationale
|
|
792
|
+
* was deleted from the old call sites and is re-homed here on purpose.
|
|
793
|
+
*/
|
|
794
|
+
private roundChildReason;
|
|
795
|
+
/** Renders an issue list as a header line plus one `- lane <i> <status>: <reason>` bullet per offending lane. */
|
|
796
|
+
private formatFanOutIssues;
|
|
797
|
+
/**
|
|
798
|
+
* Builds the parent-spine context for a blocked/errored BATCH (the escalate and
|
|
799
|
+
* errored-only join branches). WHAT it folds:
|
|
800
|
+
* - the worst lane's context (`source`) promoted back onto the spine via
|
|
801
|
+
* {@link promoteFanOutContext} (lane marker stripped, parent visit counts
|
|
802
|
+
* restored, tokens from the accumulator);
|
|
803
|
+
* - an AGGREGATED multi-lane summary of every blocked/errored lane written to
|
|
804
|
+
* `previousAgentOutput` (this is what the orchestrator reads on APPROVE→resume
|
|
805
|
+
* and the human reads in the gate banner);
|
|
806
|
+
* - the same lanes as the structured `issues` payload on
|
|
807
|
+
* `lastDeterministicResult` for the gate.
|
|
808
|
+
*
|
|
809
|
+
* WHY ONE gate, not one per offending lane: all blocked/errored reasons fold
|
|
810
|
+
* into a single payload so the human reviews the batch ONCE. The two verdict
|
|
811
|
+
* shapes differ only in `lastError`: `escalate` leaves `lastError` null (a
|
|
812
|
+
* blocked lane is recoverable, not an error), while the errored-only verdict
|
|
813
|
+
* mirrors the summary into `lastError` (the batch failed).
|
|
814
|
+
*
|
|
815
|
+
* SCRATCH-SHAPE TAG (workers:1 vs workers>1 disambiguator): the orchestrator's
|
|
816
|
+
* recovery prompt has two mutually-exclusive recoveries — legacy `evaluate`-
|
|
817
|
+
* resume of the one written-but-unscored candidate (bare `current/`) vs discard
|
|
818
|
+
* the lane scratch and start a fresh `design` batch (lane-scoped
|
|
819
|
+
* `current/lane_<k>/`). At `workers:1` the lane carries NO `lane` marker and the
|
|
820
|
+
* scratch is the BARE `current/`, so the legacy resume is the correct recovery;
|
|
821
|
+
* at `workers>1` the lane scratch is under `current/lane_<k>/` and must be
|
|
822
|
+
* discarded. The summary message alone ("Fan-out batch escalated…") would push
|
|
823
|
+
* the LLM toward discard in BOTH cases, so we append an explicit scratch-shape
|
|
824
|
+
* sentence derived from `source.context.lane` to steer the prompt's branch.
|
|
825
|
+
*/
|
|
826
|
+
private promoteFanOutIssueContext;
|
|
827
|
+
/**
|
|
828
|
+
* Promotes a SINGLE lane's context back onto the parent spine (the
|
|
829
|
+
* blocked/errored drain paths, and the `workers: 1` recorded path where there
|
|
830
|
+
* is exactly one lane). Strips the per-lane `lane` marker so the parent never
|
|
831
|
+
* carries a lane identity, restores the parent's authoritative `visitCounts`
|
|
832
|
+
* (the single-active-state spine owns visit accounting; a lane's own counts
|
|
833
|
+
* are a within-batch detail, §7.5), and reads `totalTokens` from the
|
|
834
|
+
* instance-level token accumulator (the aggregate over all lanes' registered
|
|
835
|
+
* sessionIds, which is the budget-authoritative figure, NOT the lane's local
|
|
836
|
+
* sum). The `lane === undefined` branch is the no-fan-out / `workers: 1` case:
|
|
837
|
+
* there is no lane marker to strip, so only the token figure is refreshed.
|
|
838
|
+
*/
|
|
839
|
+
private promoteFanOutContext;
|
|
840
|
+
/**
|
|
841
|
+
* Folds the N recorded lane contexts back into ONE parent-spine context at the
|
|
842
|
+
* barrier join (the recorded happy path for `workers > 1`). This is the
|
|
843
|
+
* highest-stakes merge in the fan-out: the parent FSM is single-active-state,
|
|
844
|
+
* so after the batch it must hold a single coherent context even though N
|
|
845
|
+
* child actors each evolved their own copy in parallel. Each field is merged
|
|
846
|
+
* by a rule chosen for WHY it is correct on the spine, NOT by a uniform
|
|
847
|
+
* strategy:
|
|
848
|
+
*
|
|
849
|
+
* - `visitCounts`: the PARENT's counts are authoritative and copied verbatim.
|
|
850
|
+
* The spine has a single active state (`workers`), entered once per batch;
|
|
851
|
+
* the children's per-lane visit counts are a within-batch bookkeeping detail
|
|
852
|
+
* (§7.5) that must not leak onto the parent, or the global round-limit
|
|
853
|
+
* backstop would see N× inflated counts.
|
|
854
|
+
* - `round`: SUM of each lane's POSITIVE delta over the parent baseline
|
|
855
|
+
* (`max(0, child.round - parent.round)`). A batch advanced the search by as
|
|
856
|
+
* many rounds as lanes that progressed; summing positive deltas counts each
|
|
857
|
+
* advancing lane once and ignores any lane that did not move forward.
|
|
858
|
+
* - `reviewHistory`: SUFFIX-append only — each lane's entries BEYOND the shared
|
|
859
|
+
* parent baseline are appended. Lanes start from the same parent
|
|
860
|
+
* reviewHistory, so a naive concat would replay the baseline N times; taking
|
|
861
|
+
* only the suffix past `parentContext.reviewHistory.length` avoids that N×
|
|
862
|
+
* duplication while still capturing every lane's new review notes.
|
|
863
|
+
* - `humanPrompt`: NULLED. A human prompt is a single-turn directive consumed
|
|
864
|
+
* by one state entry; it has no meaning fanned across N lanes and must not
|
|
865
|
+
* survive the batch (a stale prompt would mis-route the next orchestrator
|
|
866
|
+
* turn).
|
|
867
|
+
* - `totalTokens`: read from the instance-level accumulator (the aggregate over
|
|
868
|
+
* all lanes' registered MITM sessionIds), NOT summed from the children here —
|
|
869
|
+
* the accumulator is the budget-authoritative figure and already includes
|
|
870
|
+
* every lane's spend.
|
|
871
|
+
* - `artifacts` / `previousOutputHashes` / `agentConversationsByState`: shallow
|
|
872
|
+
* last-writer-wins merge over the parent baseline (lanes write disjoint,
|
|
873
|
+
* lane-scoped keys, so collisions are not expected; the parent baseline is
|
|
874
|
+
* the floor). The remaining scalar fields come from `last` (the
|
|
875
|
+
* highest-index lane), an arbitrary-but-deterministic representative.
|
|
876
|
+
*/
|
|
877
|
+
private mergeRecordedFanOutContext;
|
|
878
|
+
private withoutLaneContext;
|
|
879
|
+
private logFanOutJoin;
|
|
880
|
+
/**
|
|
881
|
+
* Measures effective lane diversity for one recorded batch by content-hashing
|
|
882
|
+
* each lane's candidate source and counting byte-identical collisions.
|
|
883
|
+
*
|
|
884
|
+
* WHY content-hash at fan-in (not assume effective-N = N): distinct sampled
|
|
885
|
+
* parents do NOT guarantee distinct candidates (§7.4). Convergent lanes — the
|
|
886
|
+
* researcher LLM collapsing two different parents into the same edit, or a
|
|
887
|
+
* degenerate sampler handing out overlapping parents — can produce
|
|
888
|
+
* byte-identical candidates, so "N lanes" can have an effective diversity
|
|
889
|
+
* below N. Hashing the recorded `steps/<step>/code` files surfaces that as an
|
|
890
|
+
* observable duplicate rate instead of pretending every lane added a distinct
|
|
891
|
+
* candidate; the operator reads it as a signal to tune the diversity knobs.
|
|
892
|
+
* It is a diagnostic, NOT a gate — duplicates are still recorded as distinct
|
|
893
|
+
* nodes (the engine assigns each its own id, §7.6).
|
|
894
|
+
*
|
|
895
|
+
* Every skip is best-effort, NOT an error: a missing step_name, a candidate
|
|
896
|
+
* file that does not exist yet, or a non-recorded lane is simply omitted from
|
|
897
|
+
* the sample rather than failing the join — a diagnostic must never block a
|
|
898
|
+
* batch that otherwise recorded cleanly. The `undefined` return is the
|
|
899
|
+
* "nothing measurable" contract: when no lane yielded a hashable candidate
|
|
900
|
+
* (every lane skipped), there is no diversity to report and the caller logs no
|
|
901
|
+
* duplicate stats at all (distinct from a measured `duplicateRate: 0`).
|
|
902
|
+
*/
|
|
903
|
+
private computeFanOutCandidateDuplicateStats;
|
|
904
|
+
/**
|
|
905
|
+
* The single terminal error channel from {@link runFanOutSegment} to the
|
|
906
|
+
* parent: a `result_file_error` verdict carrying `message`, which the parent
|
|
907
|
+
* `workers` state routes to its `failed` edge.
|
|
908
|
+
*/
|
|
909
|
+
private fanOutErrorResult;
|
|
417
910
|
private executeDeterministicState;
|
|
911
|
+
private applyResultFile;
|
|
912
|
+
/**
|
|
913
|
+
* Shared reduction for both deterministic execution paths: skip empty command
|
|
914
|
+
* arrays, mine the `N tests pass` heuristic from stdout, accumulate per-command
|
|
915
|
+
* failures, and shape the `{ passed, testCount, errors }` result. Host vs.
|
|
916
|
+
* container execution differ only in `runCommand` — keep that the only fork so
|
|
917
|
+
* the pass/fail and test-count semantics cannot drift between the two paths.
|
|
918
|
+
*/
|
|
919
|
+
private reduceDeterministicCommands;
|
|
920
|
+
private runDeterministicHost;
|
|
921
|
+
private runDeterministicInContainer;
|
|
418
922
|
private handleGateEntry;
|
|
419
923
|
private buildGateRequest;
|
|
420
924
|
private handleWorkflowComplete;
|