@provos/ironcurtain 0.11.0 → 0.13.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 +23 -19
- 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 +14 -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.d.ts +33 -1
- package/dist/config/config-command.js +723 -11
- 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/openrouter-catalog.d.ts +46 -0
- package/dist/config/openrouter-catalog.js +111 -0
- package/dist/config/openrouter-catalog.js.map +1 -0
- package/dist/config/openrouter-models-fallback.d.ts +15 -0
- package/dist/config/openrouter-models-fallback.js +49 -0
- package/dist/config/openrouter-models-fallback.js.map +1 -0
- 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/types.d.ts +8 -0
- package/dist/config/user-config.d.ts +179 -6
- package/dist/config/user-config.js +282 -5
- 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 +28 -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/claude-code.js +109 -1
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/adapters/codex.d.ts +18 -0
- package/dist/docker/adapters/codex.js +376 -0
- package/dist/docker/adapters/codex.js.map +1 -0
- package/dist/docker/adapters/goose.js +38 -2
- package/dist/docker/adapters/goose.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +34 -6
- 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 +486 -0
- package/dist/docker/apple-container-manager.js.map +1 -0
- package/dist/docker/ca.js +9 -2
- package/dist/docker/ca.js.map +1 -1
- 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 +9 -0
- 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.d.ts +31 -0
- package/dist/docker/docker-agent-session.js +97 -7
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +232 -15
- package/dist/docker/docker-infrastructure.js +762 -118
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +25 -5
- package/dist/docker/docker-manager.js +388 -21
- 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/docker-resource-lifecycle.d.ts +71 -0
- package/dist/docker/docker-resource-lifecycle.js +454 -0
- package/dist/docker/docker-resource-lifecycle.js.map +1 -0
- package/dist/docker/gc-command.d.ts +2 -0
- package/dist/docker/gc-command.js +37 -0
- package/dist/docker/gc-command.js.map +1 -0
- package/dist/docker/mitm-proxy.d.ts +58 -5
- package/dist/docker/mitm-proxy.js +338 -26
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/network-topology.d.ts +88 -0
- package/dist/docker/network-topology.js +167 -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/openrouter.d.ts +107 -0
- package/dist/docker/openrouter.js +236 -0
- package/dist/docker/openrouter.js.map +1 -0
- package/dist/docker/orientation.js +1 -1
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/platform.d.ts +3 -1
- package/dist/docker/platform.js +3 -1
- package/dist/docker/platform.js.map +1 -1
- package/dist/docker/provider-config.d.ts +35 -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 +22 -0
- package/dist/docker/pty-session.js +238 -84
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/docker/pty-types.d.ts +15 -0
- package/dist/docker/pty-types.js +8 -0
- package/dist/docker/pty-types.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/sse-extractor.js +55 -5
- package/dist/docker/sse-extractor.js.map +1 -1
- package/dist/docker/stream-delay.d.ts +86 -0
- package/dist/docker/stream-delay.js +218 -0
- package/dist/docker/stream-delay.js.map +1 -0
- package/dist/docker/token-stream-types.d.ts +15 -0
- 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 +1010 -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 +116 -12
- package/dist/doctor/checks.d.ts +39 -6
- package/dist/doctor/checks.js +129 -25
- 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/escalation/escalation-watcher.js +6 -0
- package/dist/escalation/escalation-watcher.js.map +1 -1
- package/dist/{mux → escalation}/trusted-input.d.ts +7 -4
- package/dist/{mux → escalation}/trusted-input.js +8 -5
- package/dist/escalation/trusted-input.js.map +1 -0
- package/dist/hash.js.map +1 -1
- package/dist/index.js +65 -16
- package/dist/index.js.map +1 -1
- package/dist/mux/mux-app.d.ts +9 -0
- package/dist/mux/mux-app.js +18 -16
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.js +26 -8
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/mux-input-handler.d.ts +26 -2
- package/dist/mux/mux-input-handler.js +93 -11
- package/dist/mux/mux-input-handler.js.map +1 -1
- package/dist/mux/mux-renderer.d.ts +2 -1
- package/dist/mux/mux-renderer.js +67 -0
- package/dist/mux/mux-renderer.js.map +1 -1
- package/dist/mux/provider-profile-snapshot.d.ts +44 -0
- package/dist/mux/provider-profile-snapshot.js +56 -0
- package/dist/mux/provider-profile-snapshot.js.map +1 -0
- package/dist/mux/types.d.ts +3 -2
- package/dist/mux/types.js +6 -2
- package/dist/mux/types.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/constitution-compiler.js.map +1 -1
- package/dist/pipeline/generate-with-repair.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/pipeline/scenario-schema-validator.js.map +1 -1
- package/dist/{mux → pty}/pty-bridge.d.ts +41 -3
- package/dist/{mux → pty}/pty-bridge.js +71 -18
- package/dist/pty/pty-bridge.js.map +1 -0
- package/dist/pty/resolve-ironcurtain-bin.d.ts +17 -0
- package/dist/pty/resolve-ironcurtain-bin.js +22 -0
- package/dist/pty/resolve-ironcurtain-bin.js.map +1 -0
- 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/servers/fetch-server.js +2 -0
- package/dist/servers/fetch-server.js.map +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +20 -2
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +20 -35
- package/dist/session/preflight.js +92 -109
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/resource-budget-tracker.js +8 -0
- package/dist/session/resource-budget-tracker.js.map +1 -1
- package/dist/session/session-manager.d.ts +7 -0
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/types.d.ts +23 -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-bot-daemon.d.ts +1 -0
- package/dist/signal/signal-bot-daemon.js +9 -2
- package/dist/signal/signal-bot-daemon.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-error-utils.js +4 -1
- package/dist/trusted-process/mcp-error-utils.js.map +1 -1
- package/dist/trusted-process/mcp-proxy-server.js +37 -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 +19 -1
- package/dist/trusted-process/tcp-server-transport.js +56 -10
- 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/utils/preflight-checks.js +1 -3
- package/dist/utils/preflight-checks.js.map +1 -1
- package/dist/utils/stdio-guard.d.ts +1 -0
- package/dist/utils/stdio-guard.js +27 -0
- package/dist/utils/stdio-guard.js.map +1 -0
- package/dist/web-ui/__tests__/config-dispatch.test.d.ts +13 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js +383 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js.map +1 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js +6 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js.map +1 -1
- 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/config-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/config-dispatch.js +277 -0
- package/dist/web-ui/dispatch/config-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/escalation-dispatch.js +11 -2
- package/dist/web-ui/dispatch/escalation-dispatch.js.map +1 -1
- 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/pty-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/pty-dispatch.js +66 -0
- package/dist/web-ui/dispatch/pty-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/session-dispatch.js +89 -6
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/types.d.ts +35 -0
- package/dist/web-ui/dispatch/types.js +42 -1
- 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 +4 -1
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
- package/dist/web-ui/pty-session-manager.d.ts +234 -0
- package/dist/web-ui/pty-session-manager.js +599 -0
- package/dist/web-ui/pty-session-manager.js.map +1 -0
- package/dist/web-ui/web-event-bus.d.ts +34 -1
- package/dist/web-ui/web-event-bus.js.map +1 -1
- package/dist/web-ui/web-session-transport.js.map +1 -1
- package/dist/web-ui/web-ui-server.d.ts +22 -0
- package/dist/web-ui/web-ui-server.js +41 -0
- package/dist/web-ui/web-ui-server.js.map +1 -1
- package/dist/web-ui/web-ui-types.d.ts +212 -5
- package/dist/web-ui/web-ui-types.js.map +1 -1
- package/dist/web-ui-static/assets/index-CCVI4nEK.css +1 -0
- package/dist/web-ui-static/assets/index-Dm012gvY.js +114 -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 +595 -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 +1725 -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/shutdown-signals.d.ts +7 -0
- package/dist/workflow/shutdown-signals.js +40 -0
- package/dist/workflow/shutdown-signals.js.map +1 -0
- 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 +118 -94
- 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/README.md +66 -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/README.md +54 -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 +28 -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 +39 -30
- 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/README.md +66 -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/README.md +54 -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/mux/pty-bridge.js.map +0 -1
- package/dist/mux/trusted-input.js.map +0 -1
- package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
- package/packages/web-ui/README.md +0 -113
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
14
14
|
import type { LanguageModel } from 'ai';
|
|
15
15
|
import type { MCPServerConfig } from '../config/types.js';
|
|
16
|
+
import { type ServerProgressReporter } from './pipeline-shared.js';
|
|
16
17
|
import type { PromptCacheStrategy } from '../session/prompt-cache.js';
|
|
17
18
|
import type { CompiledPolicyFile, CompiledRule, DynamicListsFile, ListDefinition, StoredToolAnnotationsFile, TestScenario, ToolAnnotation } from './types.js';
|
|
18
19
|
/**
|
|
@@ -67,6 +68,41 @@ export interface PipelineRunConfig {
|
|
|
67
68
|
* When undefined, the pre-filter is skipped.
|
|
68
69
|
*/
|
|
69
70
|
readonly prefilterText?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Factory for per-server progress reporters. When provided, both the
|
|
73
|
+
* sequential and parallel paths use this instead of the built-in ora/spinner
|
|
74
|
+
* (sequential) or multi-line (parallel) reporters. Non-TTY callers (e.g. the
|
|
75
|
+
* daemon driving a compile over the WS surface) inject an event-bus reporter
|
|
76
|
+
* here. Absent => the built-in reporters are used (CLI behavior).
|
|
77
|
+
*/
|
|
78
|
+
readonly reporterFactory?: (serverName: string) => ServerProgressReporter;
|
|
79
|
+
/**
|
|
80
|
+
* Cooperative cancellation. Threaded into every LLM call (`abortSignal`) and
|
|
81
|
+
* checked at each per-phase boundary so a long compile aborts promptly.
|
|
82
|
+
*/
|
|
83
|
+
readonly signal?: AbortSignal;
|
|
84
|
+
/**
|
|
85
|
+
* Suppress narrative stderr output. The daemon path sets this so progress is
|
|
86
|
+
* routed through `onProgress`/`reporterFactory` instead of polluting stderr.
|
|
87
|
+
* When `quiet` is true, a `reporterFactory` MUST be supplied — there is no
|
|
88
|
+
* silent fallback to the ora/spinner reporter (it would write to stderr).
|
|
89
|
+
*/
|
|
90
|
+
readonly quiet?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Whether the list resolver may connect to live MCP servers to resolve
|
|
93
|
+
* data-backed (`requiresMcp: true`) lists. Defaults to true (CLI). The WS
|
|
94
|
+
* compile path sets this to false: there is no live MCP available, so any
|
|
95
|
+
* list definition that requires MCP fails fast with a typed error rather than
|
|
96
|
+
* silently resolving to empty.
|
|
97
|
+
*/
|
|
98
|
+
readonly allowMcpLists?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Optional validation hook invoked on the in-memory merged policy BEFORE any
|
|
101
|
+
* artifact is written. Throwing rejects the compile and leaves all prior
|
|
102
|
+
* artifacts intact (no partial write). Used by the WS surface to enforce
|
|
103
|
+
* additional invariants (e.g. server scoping) atomically.
|
|
104
|
+
*/
|
|
105
|
+
readonly validateCompiled?: (policy: CompiledPolicyFile, dynamicLists?: DynamicListsFile) => void;
|
|
70
106
|
}
|
|
71
107
|
/**
|
|
72
108
|
* LLM model references shared across pipeline runs.
|
|
@@ -80,8 +116,14 @@ export interface PipelineModels {
|
|
|
80
116
|
/** Cheap model for pre-filter classification (Haiku). */
|
|
81
117
|
readonly prefilterModel: LanguageModel;
|
|
82
118
|
}
|
|
83
|
-
/**
|
|
84
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Creates PipelineModels from user config. Delegates to shared createPipelineLlm.
|
|
121
|
+
*
|
|
122
|
+
* `logFileName` overrides the default `llm-interactions.jsonl` filename so a
|
|
123
|
+
* caller can scope the log to a single operation (e.g. the persona compile
|
|
124
|
+
* orchestrator passes `<operationId>.jsonl`).
|
|
125
|
+
*/
|
|
126
|
+
export declare function createPipelineModels(logDir?: string, logFileName?: string): Promise<PipelineModels>;
|
|
85
127
|
/** Output from a single server's compilation cycle. */
|
|
86
128
|
interface ServerCompilationResult {
|
|
87
129
|
readonly serverName: string;
|
|
@@ -92,6 +134,23 @@ interface ServerCompilationResult {
|
|
|
92
134
|
readonly constitutionHash: string;
|
|
93
135
|
readonly resolvedLists?: DynamicListsFile;
|
|
94
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* A narrative logger for non-progress output (summaries, warnings, gaps).
|
|
139
|
+
* In quiet mode the message is routed to `onProgress` (so the daemon can
|
|
140
|
+
* surface it) instead of stderr; otherwise it goes to stderr as before.
|
|
141
|
+
*/
|
|
142
|
+
type NarrativeLogger = (message: string) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Thrown when a list definition requires live MCP access (`requiresMcp: true`)
|
|
145
|
+
* but the run was configured with `allowMcpLists: false` (e.g. the WS compile
|
|
146
|
+
* path, which has no live MCP). Carries a discriminant `code` so callers can
|
|
147
|
+
* detect it without importing this module (`error.code === 'MCP_LISTS_DISALLOWED'`).
|
|
148
|
+
*/
|
|
149
|
+
export declare class McpListsDisallowedError extends Error {
|
|
150
|
+
readonly listNames: string[];
|
|
151
|
+
readonly code = "MCP_LISTS_DISALLOWED";
|
|
152
|
+
constructor(listNames: string[]);
|
|
153
|
+
}
|
|
95
154
|
/**
|
|
96
155
|
* Computes a content hash for a single server's policy compilation inputs.
|
|
97
156
|
* The hash includes the server name, constitution, annotations, and prompt
|
|
@@ -114,7 +173,7 @@ export declare function validateServerScoping(serverName: string, rules: Compile
|
|
|
114
173
|
* generationPrompt values for the same named list, uses first-wins
|
|
115
174
|
* (alphabetical server order) and logs a warning.
|
|
116
175
|
*/
|
|
117
|
-
export declare function deduplicateListDefinitions(defs: ListDefinition[]): ListDefinition[];
|
|
176
|
+
export declare function deduplicateListDefinitions(defs: ListDefinition[], log?: NarrativeLogger): ListDefinition[];
|
|
118
177
|
/**
|
|
119
178
|
* Merges per-server compilation results into a single CompiledPolicyFile.
|
|
120
179
|
* Rules are concatenated in alphabetical server order for determinism.
|
|
@@ -123,7 +182,7 @@ export declare function deduplicateListDefinitions(defs: ListDefinition[]): List
|
|
|
123
182
|
export declare function mergeServerResults(results: ServerCompilationResult[], constitutionHash: string, skippedServers?: Array<{
|
|
124
183
|
serverName: string;
|
|
125
184
|
reason: string;
|
|
126
|
-
}
|
|
185
|
+
}>, log?: NarrativeLogger): CompiledPolicyFile;
|
|
127
186
|
/**
|
|
128
187
|
* Encapsulates the full policy compilation pipeline:
|
|
129
188
|
* compile rules -> generate scenarios -> verify -> repair loop.
|
|
@@ -20,17 +20,23 @@ import { PolicyEngine } from '../trusted-process/policy-engine.js';
|
|
|
20
20
|
import { buildCompilerSystemPrompt, ConstitutionCompilerSession, formatAnnotationsSummary, validateCompiledRules, } from './constitution-compiler.js';
|
|
21
21
|
import { getHandwrittenScenarios } from './handwritten-scenarios.js';
|
|
22
22
|
import { resolveAllLists } from './list-resolver.js';
|
|
23
|
-
import { computeHash, loadExistingArtifact, loadStoredToolAnnotationsFile, resolveRulePaths, writeArtifact, createPipelineLlm, createPerServerModel, createThrottledModel, SpinnerProgressReporter, } from './pipeline-shared.js';
|
|
23
|
+
import { computeHash, loadExistingArtifact, loadStoredToolAnnotationsFile, resolveRulePaths, writeArtifact, removeArtifactIfExists, createPipelineLlm, createPerServerModel, createThrottledModel, SpinnerProgressReporter, } from './pipeline-shared.js';
|
|
24
24
|
import { resolveStoredAnnotationsFile } from '../types/argument-roles.js';
|
|
25
25
|
import { applyScenarioCorrections, buildJudgeSystemPrompt, detectAllDefaultRoleFallbacks, extractScenarioCorrections, filterStructuralConflicts, PolicyVerifierSession, verifyPolicy, } from './policy-verifier.js';
|
|
26
26
|
import { filterInvalidSchemaScenarios } from './scenario-schema-validator.js';
|
|
27
27
|
import { buildGeneratorSystemPrompt, generateScenarios, repairScenarios } from './scenario-generator.js';
|
|
28
28
|
import { prefilterServers } from './server-prefilter.js';
|
|
29
29
|
import { connectViaProxy } from './proxy-mcp-connections.js';
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Creates PipelineModels from user config. Delegates to shared createPipelineLlm.
|
|
32
|
+
*
|
|
33
|
+
* `logFileName` overrides the default `llm-interactions.jsonl` filename so a
|
|
34
|
+
* caller can scope the log to a single operation (e.g. the persona compile
|
|
35
|
+
* orchestrator passes `<operationId>.jsonl`).
|
|
36
|
+
*/
|
|
37
|
+
export async function createPipelineModels(logDir, logFileName) {
|
|
32
38
|
const effectiveLogDir = logDir ?? resolve(process.cwd(), 'generated');
|
|
33
|
-
const llm = await createPipelineLlm(effectiveLogDir, 'unknown');
|
|
39
|
+
const llm = await createPipelineLlm(effectiveLogDir, 'unknown', logFileName);
|
|
34
40
|
const userConfig = loadUserConfig();
|
|
35
41
|
const haikuBaseLlm = await createLanguageModel(userConfig.prefilterModelId, userConfig);
|
|
36
42
|
const { model: prefilterModel } = createPerServerModel(haikuBaseLlm, llm.logPath, 'prefilter');
|
|
@@ -57,18 +63,20 @@ function computeScenariosHash(systemPrompt, handwrittenScenarios) {
|
|
|
57
63
|
* `mcpServers` may be undefined when compile-policy is run with `--no-mcp`,
|
|
58
64
|
* in which case the check is skipped.
|
|
59
65
|
*/
|
|
60
|
-
function warnOnCompileAnnotationGaps(mcpServers, storedAnnotationsFile) {
|
|
66
|
+
function warnOnCompileAnnotationGaps(mcpServers, storedAnnotationsFile, log = (msg) => {
|
|
67
|
+
console.error(msg);
|
|
68
|
+
}) {
|
|
61
69
|
if (!mcpServers)
|
|
62
70
|
return;
|
|
63
71
|
const { missing } = findAnnotationServerDrift(storedAnnotationsFile, mcpServers);
|
|
64
72
|
if (missing.length === 0)
|
|
65
73
|
return;
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
log(chalk.yellow(`Warning: ${missing.length} configured MCP server(s) have no tool annotations: ${missing.map(safeForDisplay).join(', ')}.`));
|
|
75
|
+
log(chalk.yellow(' The compiled policy will have no rules for these servers and their tools will be denied.'));
|
|
68
76
|
for (const name of missing) {
|
|
69
|
-
|
|
77
|
+
log(chalk.yellow(` Run \`ironcurtain annotate-tools --server ${safeForDisplay(name)}\` to annotate this server.`));
|
|
70
78
|
}
|
|
71
|
-
|
|
79
|
+
log('');
|
|
72
80
|
}
|
|
73
81
|
function extractPermittedDirectories(rules) {
|
|
74
82
|
const dirs = new Set();
|
|
@@ -131,6 +139,31 @@ function filterAndLogStructuralConflicts(engine, scenarios, label = 'Discarded s
|
|
|
131
139
|
function toError(err) {
|
|
132
140
|
return err instanceof Error ? err : new Error(String(err));
|
|
133
141
|
}
|
|
142
|
+
function makeNarrativeLogger(config) {
|
|
143
|
+
if (config.quiet) {
|
|
144
|
+
const onProgress = config.onProgress;
|
|
145
|
+
return (msg) => {
|
|
146
|
+
onProgress?.(msg);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return (msg) => {
|
|
150
|
+
console.error(msg);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Resolves the reporter for a server. A caller-supplied `reporterFactory`
|
|
155
|
+
* always wins. When absent: quiet mode has NO fallback (the built-in reporters
|
|
156
|
+
* write to stderr), so it is a configuration error; non-quiet mode uses the
|
|
157
|
+
* built-in concrete reporter via `makeDefault`.
|
|
158
|
+
*/
|
|
159
|
+
function resolveReporter(config, serverName, makeDefault) {
|
|
160
|
+
if (config.reporterFactory)
|
|
161
|
+
return config.reporterFactory(serverName);
|
|
162
|
+
if (config.quiet) {
|
|
163
|
+
throw new Error(`quiet:true requires a reporterFactory; no stderr-free reporter is available for server "${serverName}".`);
|
|
164
|
+
}
|
|
165
|
+
return makeDefault();
|
|
166
|
+
}
|
|
134
167
|
class RuleValidationError extends Error {
|
|
135
168
|
errors;
|
|
136
169
|
constructor(errors) {
|
|
@@ -139,6 +172,23 @@ class RuleValidationError extends Error {
|
|
|
139
172
|
this.name = 'RuleValidationError';
|
|
140
173
|
}
|
|
141
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Thrown when a list definition requires live MCP access (`requiresMcp: true`)
|
|
177
|
+
* but the run was configured with `allowMcpLists: false` (e.g. the WS compile
|
|
178
|
+
* path, which has no live MCP). Carries a discriminant `code` so callers can
|
|
179
|
+
* detect it without importing this module (`error.code === 'MCP_LISTS_DISALLOWED'`).
|
|
180
|
+
*/
|
|
181
|
+
export class McpListsDisallowedError extends Error {
|
|
182
|
+
listNames;
|
|
183
|
+
code = 'MCP_LISTS_DISALLOWED';
|
|
184
|
+
constructor(listNames) {
|
|
185
|
+
super(`Dynamic list(s) require live MCP access but it is disabled (allowMcpLists: false): ` +
|
|
186
|
+
`${listNames.join(', ')}. Resolve these lists in an environment with MCP available, ` +
|
|
187
|
+
`or remove the MCP-backed list definitions.`);
|
|
188
|
+
this.listNames = listNames;
|
|
189
|
+
this.name = 'McpListsDisallowedError';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
142
192
|
function validateRulesOrThrow(rules, listDefinitions = [], reporter) {
|
|
143
193
|
const warn = (msg) => (reporter ? reporter.warn(msg) : console.error(msg));
|
|
144
194
|
const ruleValidation = validateCompiledRules(rules, listDefinitions);
|
|
@@ -279,7 +329,9 @@ export function validateServerScoping(serverName, rules) {
|
|
|
279
329
|
* generationPrompt values for the same named list, uses first-wins
|
|
280
330
|
* (alphabetical server order) and logs a warning.
|
|
281
331
|
*/
|
|
282
|
-
export function deduplicateListDefinitions(defs) {
|
|
332
|
+
export function deduplicateListDefinitions(defs, log = (msg) => {
|
|
333
|
+
console.error(msg);
|
|
334
|
+
}) {
|
|
283
335
|
const seen = new Map();
|
|
284
336
|
for (const def of defs) {
|
|
285
337
|
const existing = seen.get(def.name);
|
|
@@ -287,7 +339,7 @@ export function deduplicateListDefinitions(defs) {
|
|
|
287
339
|
seen.set(def.name, def);
|
|
288
340
|
}
|
|
289
341
|
else if (existing.generationPrompt !== def.generationPrompt) {
|
|
290
|
-
|
|
342
|
+
log(` Warning: list "${def.name}" has divergent generation prompts ` +
|
|
291
343
|
`across servers. Using first definition (alphabetical server order).`);
|
|
292
344
|
}
|
|
293
345
|
}
|
|
@@ -298,11 +350,11 @@ export function deduplicateListDefinitions(defs) {
|
|
|
298
350
|
* Rules are concatenated in alphabetical server order for determinism.
|
|
299
351
|
* List definitions are deduplicated by name.
|
|
300
352
|
*/
|
|
301
|
-
export function mergeServerResults(results, constitutionHash, skippedServers) {
|
|
353
|
+
export function mergeServerResults(results, constitutionHash, skippedServers, log) {
|
|
302
354
|
const sortedResults = [...results].sort((a, b) => a.serverName.localeCompare(b.serverName));
|
|
303
355
|
const allRules = sortedResults.flatMap((r) => r.rules);
|
|
304
356
|
const allListDefs = sortedResults.flatMap((r) => r.listDefinitions);
|
|
305
|
-
const uniqueListDefs = deduplicateListDefinitions(allListDefs);
|
|
357
|
+
const uniqueListDefs = deduplicateListDefinitions(allListDefs, log);
|
|
306
358
|
const mergedInputHash = computeHash(...sortedResults.map((r) => r.inputHash));
|
|
307
359
|
const artifact = {
|
|
308
360
|
generatedAt: new Date().toISOString(),
|
|
@@ -366,21 +418,22 @@ export class PipelineRunner {
|
|
|
366
418
|
* to select the appropriate compiler prompt.
|
|
367
419
|
*/
|
|
368
420
|
async runPerServer(config) {
|
|
421
|
+
const log = makeNarrativeLogger(config);
|
|
422
|
+
config.signal?.throwIfAborted();
|
|
369
423
|
const storedAnnotationsFile = config.preloadedStoredAnnotations ??
|
|
370
424
|
loadStoredToolAnnotationsFile(config.toolAnnotationsDir, config.toolAnnotationsFallbackDir);
|
|
371
425
|
if (!storedAnnotationsFile) {
|
|
372
426
|
throw new Error("tool-annotations.json not found. Run 'ironcurtain annotate-tools' first.");
|
|
373
427
|
}
|
|
374
|
-
warnOnCompileAnnotationGaps(config.mcpServers, storedAnnotationsFile);
|
|
428
|
+
warnOnCompileAnnotationGaps(config.mcpServers, storedAnnotationsFile, log);
|
|
375
429
|
// Resolve conditional role specs to flat annotations for compiler prompts
|
|
376
430
|
const toolAnnotationsFile = resolveStoredAnnotationsFile(storedAnnotationsFile);
|
|
377
431
|
const constitutionHash = computeHash(config.constitutionInput);
|
|
378
432
|
// Phase 1: Per-server compilation (with optional Haiku pre-filter)
|
|
379
433
|
const { results: serverResults, skippedServers } = await this.compileAllServers(config, toolAnnotationsFile, constitutionHash, storedAnnotationsFile);
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
// Merge scenarios for the global artifact
|
|
434
|
+
config.signal?.throwIfAborted();
|
|
435
|
+
// Phase 2: Merge (all three artifacts assembled in memory before any write)
|
|
436
|
+
const mergedPolicy = mergeServerResults(serverResults, constitutionHash, skippedServers, log);
|
|
384
437
|
const allScenarios = serverResults.flatMap((r) => r.scenarios);
|
|
385
438
|
const mergedScenariosFile = {
|
|
386
439
|
generatedAt: new Date().toISOString(),
|
|
@@ -388,10 +441,10 @@ export class PipelineRunner {
|
|
|
388
441
|
inputHash: mergedPolicy.inputHash,
|
|
389
442
|
scenarios: allScenarios,
|
|
390
443
|
};
|
|
391
|
-
|
|
392
|
-
// Phase 3: Merge per-server resolved lists into global dynamic-lists.json
|
|
444
|
+
// Phase 3: Merge per-server resolved lists into the global dynamic-lists.json.
|
|
393
445
|
// Each server resolved its own lists during compileServer(); merge them here.
|
|
394
446
|
const listDefinitions = mergedPolicy.listDefinitions ?? [];
|
|
447
|
+
let mergedDynamicLists;
|
|
395
448
|
if (listDefinitions.length > 0) {
|
|
396
449
|
const keptListNames = new Set(listDefinitions.map((d) => d.name));
|
|
397
450
|
const mergedListEntries = {};
|
|
@@ -406,12 +459,34 @@ export class PipelineRunner {
|
|
|
406
459
|
}
|
|
407
460
|
}
|
|
408
461
|
}
|
|
409
|
-
|
|
462
|
+
mergedDynamicLists = {
|
|
410
463
|
generatedAt: new Date().toISOString(),
|
|
411
464
|
lists: mergedListEntries,
|
|
412
465
|
};
|
|
466
|
+
}
|
|
467
|
+
// Optional caller validation runs on the in-memory policy BEFORE any artifact
|
|
468
|
+
// is written, so a rejection leaves the prior generation's files intact.
|
|
469
|
+
config.validateCompiled?.(mergedPolicy, mergedDynamicLists);
|
|
470
|
+
// Write order is the REVERSE of the runtime read order in
|
|
471
|
+
// loadPersonaPolicyArtifacts (compiled-policy first, then dynamic-lists):
|
|
472
|
+
// 1. dynamic-lists.json (or atomically REMOVE the stale file when there
|
|
473
|
+
// are no list definitions — fixing the previous skip-leaves-stale bug)
|
|
474
|
+
// 2. test-scenarios.json
|
|
475
|
+
// 3. compiled-policy.json LAST
|
|
476
|
+
// Each write is per-file atomic (tmp + rename). The dependency ordering
|
|
477
|
+
// guarantees a concurrent reader that observes the NEW compiled-policy.json
|
|
478
|
+
// already sees the matching dynamic-lists.json; the reverse interleaving
|
|
479
|
+
// (new lists + old compiled) is fail-safe because an unknown @list-id
|
|
480
|
+
// resolves to the empty allowlist => deny (PolicyEngine.getEffectiveListValues
|
|
481
|
+
// returns [] for a missing list rather than throwing).
|
|
482
|
+
if (mergedDynamicLists) {
|
|
413
483
|
writeArtifact(config.outputDir, 'dynamic-lists.json', mergedDynamicLists);
|
|
414
484
|
}
|
|
485
|
+
else {
|
|
486
|
+
removeArtifactIfExists(config.outputDir, 'dynamic-lists.json');
|
|
487
|
+
}
|
|
488
|
+
writeArtifact(config.outputDir, 'test-scenarios.json', mergedScenariosFile);
|
|
489
|
+
writeArtifact(config.outputDir, 'compiled-policy.json', mergedPolicy);
|
|
415
490
|
// Cross-server verification is intentionally omitted. Per-server rules compose
|
|
416
491
|
// correctly by construction: every rule has server: [serverName] (enforced by
|
|
417
492
|
// Zod schema), the engine checks cond.server.includes(request.serverName) so
|
|
@@ -423,16 +498,16 @@ export class PipelineRunner {
|
|
|
423
498
|
const totalRules = mergedPolicy.rules.length;
|
|
424
499
|
const totalScenarios = allScenarios.length;
|
|
425
500
|
const serverCount = serverResults.length;
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
501
|
+
log('');
|
|
502
|
+
log(` Servers compiled: ${serverCount}`);
|
|
503
|
+
log(` Rules: ${totalRules}`);
|
|
504
|
+
log(` Scenarios tested: ${totalScenarios}`);
|
|
505
|
+
log(` Artifacts written to: ${chalk.dim(config.outputDir + '/')}`);
|
|
431
506
|
if (config.llmLogPath) {
|
|
432
|
-
|
|
507
|
+
log(` LLM interaction log: ${chalk.dim(config.llmLogPath)}`);
|
|
433
508
|
}
|
|
434
|
-
|
|
435
|
-
|
|
509
|
+
log('');
|
|
510
|
+
log(chalk.green.bold('Policy compilation successful!'));
|
|
436
511
|
return mergedPolicy;
|
|
437
512
|
}
|
|
438
513
|
/**
|
|
@@ -441,6 +516,7 @@ export class PipelineRunner {
|
|
|
441
516
|
* Multi-server compilation uses parallel execution with a multi-line progress display.
|
|
442
517
|
*/
|
|
443
518
|
async compileAllServers(config, toolAnnotationsFile, constitutionHash, storedAnnotationsFile) {
|
|
519
|
+
const log = makeNarrativeLogger(config);
|
|
444
520
|
const serverEntries = Object.entries(toolAnnotationsFile.servers);
|
|
445
521
|
// Apply server filter if provided
|
|
446
522
|
const { serverFilter } = config;
|
|
@@ -457,7 +533,7 @@ export class PipelineRunner {
|
|
|
457
533
|
if (config.prefilterText !== undefined && !config.serverFilter) {
|
|
458
534
|
const prefilterText = config.prefilterText;
|
|
459
535
|
if (prefilterText.trim() === '') {
|
|
460
|
-
|
|
536
|
+
log(chalk.yellow('Pre-filter input is empty. All servers skipped (default-deny applies).'));
|
|
461
537
|
const allSkipped = filteredEntries.map(([name]) => ({
|
|
462
538
|
serverName: name,
|
|
463
539
|
reason: 'No input text provided — all servers skipped by default',
|
|
@@ -470,7 +546,7 @@ export class PipelineRunner {
|
|
|
470
546
|
entriesToCompile = filteredEntries.filter(([name]) => {
|
|
471
547
|
const decision = decisionMap.get(name);
|
|
472
548
|
if (decision?.skip) {
|
|
473
|
-
|
|
549
|
+
log(` ${chalk.dim(name)}: ${chalk.yellow('skipped')} — ${decision.reason}`);
|
|
474
550
|
skippedServers.push({ serverName: name, reason: decision.reason });
|
|
475
551
|
return false;
|
|
476
552
|
}
|
|
@@ -478,11 +554,11 @@ export class PipelineRunner {
|
|
|
478
554
|
});
|
|
479
555
|
const skippedCount = filteredEntries.length - entriesToCompile.length;
|
|
480
556
|
if (skippedCount > 0) {
|
|
481
|
-
|
|
557
|
+
log(` Pre-filter: ${skippedCount} server(s) skipped, ${entriesToCompile.length} proceeding`);
|
|
482
558
|
}
|
|
483
559
|
}
|
|
484
560
|
if (entriesToCompile.length === 0) {
|
|
485
|
-
|
|
561
|
+
log(chalk.yellow('All servers skipped by pre-filter. Policy will use default-deny only.'));
|
|
486
562
|
return { results: [], skippedServers };
|
|
487
563
|
}
|
|
488
564
|
// Load handwritten scenarios once, then filter per server (avoids N redundant loads)
|
|
@@ -513,20 +589,22 @@ export class PipelineRunner {
|
|
|
513
589
|
return { results, skippedServers };
|
|
514
590
|
}
|
|
515
591
|
/** Creates a per-server model wrapped with LLM call throttling. */
|
|
516
|
-
createServerModel(serverName, llmSemaphore) {
|
|
592
|
+
createServerModel(serverName, llmSemaphore, signal) {
|
|
517
593
|
const { model, logContext } = createPerServerModel(this.baseLlm, this.logPath, serverName);
|
|
518
|
-
return { model: createThrottledModel(model, llmSemaphore), logContext };
|
|
594
|
+
return { model: createThrottledModel(model, llmSemaphore, signal), logContext };
|
|
519
595
|
}
|
|
520
596
|
async compileServersSequential(filteredEntries, config, constitutionHash, buildUnit, llmSemaphore) {
|
|
597
|
+
const log = makeNarrativeLogger(config);
|
|
521
598
|
const results = [];
|
|
522
599
|
const totalServers = filteredEntries.length;
|
|
523
600
|
const failedServers = [];
|
|
524
601
|
for (let i = 0; i < filteredEntries.length; i++) {
|
|
602
|
+
config.signal?.throwIfAborted();
|
|
525
603
|
const [serverName] = filteredEntries[i];
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const { model, logContext } = this.createServerModel(serverName, llmSemaphore);
|
|
529
|
-
const reporter = new SpinnerProgressReporter(serverName);
|
|
604
|
+
log('');
|
|
605
|
+
log(chalk.bold(`[${i + 1}/${totalServers}] Compiling server: ${serverName}`));
|
|
606
|
+
const { model, logContext } = this.createServerModel(serverName, llmSemaphore, config.signal);
|
|
607
|
+
const reporter = resolveReporter(config, serverName, () => new SpinnerProgressReporter(serverName));
|
|
530
608
|
try {
|
|
531
609
|
const result = await this.compileServer(buildUnit(serverName), config, constitutionHash, model, logContext, reporter);
|
|
532
610
|
results.push(result);
|
|
@@ -534,20 +612,36 @@ export class PipelineRunner {
|
|
|
534
612
|
catch (err) {
|
|
535
613
|
const coerced = toError(err);
|
|
536
614
|
reporter.fail('compiling', coerced);
|
|
537
|
-
|
|
615
|
+
// A disabled-MCP-list error is a run-level configuration failure, not a
|
|
616
|
+
// per-server verification failure. Surface it past the failedServers
|
|
617
|
+
// aggregation so the orchestrator can map it to LIST_REQUIRES_MCP
|
|
618
|
+
// instead of the generic "all servers failed compilation" error.
|
|
619
|
+
if (err instanceof McpListsDisallowedError)
|
|
620
|
+
throw err;
|
|
621
|
+
log(` ${chalk.red(`Server "${serverName}" failed:`)} ${coerced.message}`);
|
|
538
622
|
failedServers.push(serverName);
|
|
539
623
|
}
|
|
540
624
|
}
|
|
541
|
-
return this.handleCompilationResults(results, failedServers);
|
|
625
|
+
return this.handleCompilationResults(results, failedServers, log);
|
|
542
626
|
}
|
|
543
627
|
async compileServersParallel(filteredEntries, config, constitutionHash, buildUnit, llmSemaphore, serverLimit) {
|
|
628
|
+
const log = makeNarrativeLogger(config);
|
|
544
629
|
// Lazy import to avoid loading parallel-progress.ts when not needed
|
|
545
630
|
const { ParallelProgressDisplay, ParallelProgressReporter } = await import('./parallel-progress.js');
|
|
546
631
|
const serverNames = filteredEntries.map(([name]) => name);
|
|
547
|
-
|
|
632
|
+
// When a reporterFactory is injected the caller drives its own display; the
|
|
633
|
+
// built-in multi-line ParallelProgressDisplay would write to stderr, so it
|
|
634
|
+
// is only constructed for the built-in reporter path.
|
|
635
|
+
const display = config.reporterFactory ? undefined : new ParallelProgressDisplay(serverNames);
|
|
548
636
|
const settled = await Promise.allSettled(filteredEntries.map(([serverName]) => serverLimit(async () => {
|
|
549
|
-
|
|
550
|
-
const
|
|
637
|
+
config.signal?.throwIfAborted();
|
|
638
|
+
const { model, logContext } = this.createServerModel(serverName, llmSemaphore, config.signal);
|
|
639
|
+
const reporter = resolveReporter(config, serverName, () => {
|
|
640
|
+
// `display` is defined whenever reporterFactory is absent (built-in path).
|
|
641
|
+
if (!display)
|
|
642
|
+
throw new Error('internal: built-in parallel display missing');
|
|
643
|
+
return new ParallelProgressReporter(display, serverName);
|
|
644
|
+
});
|
|
551
645
|
try {
|
|
552
646
|
return await this.compileServer(buildUnit(serverName), config, constitutionHash, model, logContext, reporter);
|
|
553
647
|
}
|
|
@@ -556,7 +650,7 @@ export class PipelineRunner {
|
|
|
556
650
|
throw err;
|
|
557
651
|
}
|
|
558
652
|
})));
|
|
559
|
-
display
|
|
653
|
+
display?.finish();
|
|
560
654
|
const results = [];
|
|
561
655
|
const failedServers = [];
|
|
562
656
|
for (const [i, outcome] of settled.entries()) {
|
|
@@ -564,16 +658,21 @@ export class PipelineRunner {
|
|
|
564
658
|
results.push(outcome.value);
|
|
565
659
|
}
|
|
566
660
|
else {
|
|
661
|
+
// A disabled-MCP-list error is a run-level configuration failure, not a
|
|
662
|
+
// per-server verification failure. Surface it past the failedServers
|
|
663
|
+
// aggregation so the orchestrator can map it to LIST_REQUIRES_MCP.
|
|
664
|
+
if (outcome.reason instanceof McpListsDisallowedError)
|
|
665
|
+
throw outcome.reason;
|
|
567
666
|
const serverName = filteredEntries[i][0];
|
|
568
667
|
failedServers.push(serverName);
|
|
569
668
|
}
|
|
570
669
|
}
|
|
571
|
-
return this.handleCompilationResults(results, failedServers);
|
|
670
|
+
return this.handleCompilationResults(results, failedServers, log);
|
|
572
671
|
}
|
|
573
|
-
handleCompilationResults(results, failedServers) {
|
|
672
|
+
handleCompilationResults(results, failedServers, log) {
|
|
574
673
|
if (failedServers.length > 0) {
|
|
575
|
-
|
|
576
|
-
|
|
674
|
+
log(`\n${chalk.yellow(`Warning: ${failedServers.length} server(s) failed verification: ${failedServers.join(', ')}`)}`);
|
|
675
|
+
log(chalk.yellow('Continuing with successfully compiled servers.'));
|
|
577
676
|
}
|
|
578
677
|
if (results.length === 0) {
|
|
579
678
|
throw new Error(`All ${failedServers.length} server(s) failed compilation: ${failedServers.join(', ')}. ` +
|
|
@@ -619,6 +718,7 @@ export class PipelineRunner {
|
|
|
619
718
|
}
|
|
620
719
|
const compilerSystem = this.cacheStrategy.wrapSystemPrompt(compilerPrompt);
|
|
621
720
|
// Step 1: Compile rules for this server
|
|
721
|
+
config.signal?.throwIfAborted();
|
|
622
722
|
logContext.stepName = `compile-${unit.serverName}`;
|
|
623
723
|
const compileResult = await this.compileServerPolicyRules(unit, compilerSystem, inputHash, model, reporter);
|
|
624
724
|
let { rules } = compileResult;
|
|
@@ -626,6 +726,7 @@ export class PipelineRunner {
|
|
|
626
726
|
// Validate server scoping (debug assertion)
|
|
627
727
|
validateServerScoping(unit.serverName, rules);
|
|
628
728
|
// Resolve dynamic lists for this server (before scenario generation so lists are available)
|
|
729
|
+
config.signal?.throwIfAborted();
|
|
629
730
|
let dynamicLists;
|
|
630
731
|
if (listDefinitions.length > 0) {
|
|
631
732
|
dynamicLists = await this.resolveServerLists(listDefinitions, serverOutputDir, config, ` ${unit.serverName}`, model, logContext, reporter);
|
|
@@ -652,12 +753,14 @@ export class PipelineRunner {
|
|
|
652
753
|
? extractServerDomainAllowlists({ [unit.serverName]: unit.mcpServerConfig })
|
|
653
754
|
: undefined;
|
|
654
755
|
// Step 2: Generate test scenarios for this server
|
|
756
|
+
config.signal?.throwIfAborted();
|
|
655
757
|
logContext.stepName = `scenarios-${unit.serverName}`;
|
|
656
758
|
const permittedDirectories = extractPermittedDirectories(rules);
|
|
657
759
|
const scenarioPrompt = buildGeneratorSystemPrompt(unit.constitutionText, unit.storedAnnotations, unit.allowedDirectory, permittedDirectories, dynamicLists);
|
|
658
760
|
const scenarioHash = computeScenariosHash(scenarioPrompt, unit.handwrittenScenarios);
|
|
659
761
|
const scenarioResult = await this.generateTestScenarios(unit.constitutionText, unit.storedAnnotations, unit.allowedDirectory, unit.handwrittenScenarios, scenarioHash, existingServerScenarios, ` ${unit.serverName}`, permittedDirectories, dynamicLists, model, reporter);
|
|
660
762
|
// Step 3: Verify and repair
|
|
763
|
+
config.signal?.throwIfAborted();
|
|
661
764
|
const state = await this.verifyAndRepairServer(unit, config, constitutionHash, inputHash, serverPolicyFile, serverAnnotationsFile, serverDomainAllowlists, dynamicLists, rules, listDefinitions, compileResult.session, scenarioResult, permittedDirectories, compilerSystem, model, logContext, reporter, serverOutputDir, writeServerPolicy);
|
|
662
765
|
// Sync repaired state back so the writeServerPolicy closure sees updated values
|
|
663
766
|
rules = state.rules;
|
|
@@ -943,7 +1046,13 @@ export class PipelineRunner {
|
|
|
943
1046
|
async resolveServerLists(listDefinitions, serverOutputDir, config, labelPrefix, model, logContext, reporter) {
|
|
944
1047
|
logContext.stepName = `resolve-lists-${labelPrefix.trim()}`;
|
|
945
1048
|
const existingLists = loadExistingArtifact(serverOutputDir, 'dynamic-lists.json');
|
|
946
|
-
const
|
|
1049
|
+
const mcpListNames = listDefinitions.filter((d) => d.requiresMcp).map((d) => d.name);
|
|
1050
|
+
const needsMcp = mcpListNames.length > 0;
|
|
1051
|
+
// The WS compile path disables live MCP. Fail fast with a typed error rather
|
|
1052
|
+
// than silently resolving MCP-backed lists to empty (which would deny).
|
|
1053
|
+
if (needsMcp && config.allowMcpLists === false) {
|
|
1054
|
+
throw new McpListsDisallowedError(mcpListNames);
|
|
1055
|
+
}
|
|
947
1056
|
let proxy;
|
|
948
1057
|
if (needsMcp && config.mcpServers) {
|
|
949
1058
|
proxy = await connectViaProxy(listDefinitions, config.mcpServers, config.toolAnnotationsDir);
|