@sema-agent/server 1.323.0 → 2.0.1
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/dist/approval-hmac.d.ts +40 -0
- package/dist/approval-hmac.js +67 -0
- package/dist/approval.d.ts +31 -0
- package/dist/approval.js +72 -4
- package/dist/audit.d.ts +26 -0
- package/dist/audit.js +40 -1
- package/dist/auth-bridge.d.ts +10 -0
- package/dist/auth-bridge.js +47 -4
- package/dist/auth-keys.d.ts +19 -0
- package/dist/auth-keys.js +13 -0
- package/dist/bake-runner/main.d.ts +5 -0
- package/dist/bake-runner/main.js +43 -4
- package/dist/bake-runner/protocol.d.ts +57 -0
- package/dist/bake-runner/protocol.js +58 -3
- package/dist/bake-runner/runner.d.ts +54 -0
- package/dist/bake-runner/runner.js +87 -5
- package/dist/bench/l8/artifact.d.ts +63 -0
- package/dist/bench/l8/artifact.js +61 -2
- package/dist/bench/l8/escape.d.ts +36 -0
- package/dist/bench/l8/escape.js +25 -0
- package/dist/bench/l8/index.d.ts +14 -0
- package/dist/bench/l8/index.js +14 -0
- package/dist/bench/l8/probes.d.ts +74 -0
- package/dist/bench/l8/probes.js +60 -0
- package/dist/bench/l8/run-probes.d.ts +43 -0
- package/dist/bench/l8/run-probes.js +45 -2
- package/dist/bench/s1/arms.d.ts +126 -0
- package/dist/bench/s1/arms.js +188 -13
- package/dist/bench/s1/live-deps.d.ts +66 -0
- package/dist/bench/s1/live-deps.js +249 -11
- package/dist/bench/s1/oracle.d.ts +49 -0
- package/dist/bench/s1/oracle.js +36 -1
- package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
- package/dist/bench/s1/repair-oracle-adapter.js +30 -0
- package/dist/bench/s1/reviewer.d.ts +38 -0
- package/dist/bench/s1/reviewer.js +34 -0
- package/dist/bench/s1/row.d.ts +77 -0
- package/dist/bench/s1/row.js +62 -0
- package/dist/bench/s1/run-firm.d.ts +47 -0
- package/dist/bench/s1/run-firm.js +70 -4
- package/dist/bench/s1/runner-ctx.d.ts +71 -0
- package/dist/bench/s1/runner-ctx.js +36 -0
- package/dist/bench/s1/tasks.d.ts +108 -0
- package/dist/bench/s1/tasks.js +115 -0
- package/dist/boot/budget-tracing.d.ts +48 -0
- package/dist/boot/budget-tracing.js +86 -0
- package/dist/boot/config-center.d.ts +62 -0
- package/dist/boot/config-center.js +995 -0
- package/dist/boot/coordinators.d.ts +33 -0
- package/dist/boot/coordinators.js +97 -0
- package/dist/boot/execution-env.d.ts +26 -0
- package/dist/boot/execution-env.js +370 -0
- package/dist/boot/leader.d.ts +27 -0
- package/dist/boot/leader.js +81 -0
- package/dist/boot/reapers.d.ts +53 -0
- package/dist/boot/reapers.js +252 -0
- package/dist/boot/resolve-spec.d.ts +70 -0
- package/dist/boot/resolve-spec.js +1072 -0
- package/dist/boot/runner-deps.d.ts +101 -0
- package/dist/boot/runner-deps.js +343 -0
- package/dist/boot/runtime-caps.d.ts +21 -0
- package/dist/boot/runtime-caps.js +62 -0
- package/dist/boot/session-faces.d.ts +57 -0
- package/dist/boot/session-faces.js +157 -0
- package/dist/boot/shutdown.d.ts +50 -0
- package/dist/boot/shutdown.js +129 -0
- package/dist/boot/stores.d.ts +32 -0
- package/dist/boot/stores.js +361 -0
- package/dist/boot/workflow-orchestration.d.ts +46 -0
- package/dist/boot/workflow-orchestration.js +150 -0
- package/dist/boot-reclaim.d.ts +19 -0
- package/dist/boot-reclaim.js +20 -0
- package/dist/brain.d.ts +25 -0
- package/dist/brain.js +61 -1
- package/dist/budget.d.ts +66 -0
- package/dist/budget.js +128 -4
- package/dist/capabilities/builtin-tools.d.ts +3 -0
- package/dist/capabilities/builtin-tools.js +3 -0
- package/dist/capabilities/center-plugins.d.ts +17 -1
- package/dist/capabilities/center-plugins.js +45 -4
- package/dist/capabilities/center-prompts.d.ts +46 -0
- package/dist/capabilities/center-prompts.js +57 -3
- package/dist/capabilities/code-review-council.d.ts +28 -0
- package/dist/capabilities/code-review-council.js +40 -7
- package/dist/capabilities/collab-wire.d.ts +2 -0
- package/dist/capabilities/collab-workflows.d.ts +7 -0
- package/dist/capabilities/collab-workflows.js +44 -1
- package/dist/capabilities/oa-tools.d.ts +6 -0
- package/dist/capabilities/oa-tools.js +10 -0
- package/dist/capabilities/prompt.d.ts +14 -0
- package/dist/capabilities/prompt.js +14 -0
- package/dist/capabilities/prompts/code-review.d.ts +14 -0
- package/dist/capabilities/prompts/code-review.js +14 -0
- package/dist/capabilities/prompts/identity.d.ts +6 -0
- package/dist/capabilities/prompts/identity.js +6 -0
- package/dist/capabilities/prompts/team.d.ts +4 -0
- package/dist/capabilities/prompts/team.js +4 -0
- package/dist/capabilities/repo-tools.d.ts +11 -0
- package/dist/capabilities/repo-tools.js +8 -0
- package/dist/capabilities/sandbox-file-send.d.ts +95 -0
- package/dist/capabilities/sandbox-file-send.js +91 -3
- package/dist/capabilities/scenarios.d.ts +130 -0
- package/dist/capabilities/scenarios.js +180 -7
- package/dist/capabilities/select-environment-tool.d.ts +7 -0
- package/dist/capabilities/select-environment-tool.js +30 -0
- package/dist/capabilities/send-user-file-tool.d.ts +33 -0
- package/dist/capabilities/send-user-file-tool.js +65 -1
- package/dist/capabilities/skills.d.ts +29 -0
- package/dist/capabilities/skills.js +13 -2
- package/dist/capabilities/team.d.ts +22 -0
- package/dist/capabilities/team.js +22 -2
- package/dist/capabilities/tool-defer.d.ts +26 -0
- package/dist/capabilities/tool-defer.js +3 -0
- package/dist/config-center/apply-effective.d.ts +65 -0
- package/dist/config-center/apply-effective.js +204 -12
- package/dist/config-center/http-client.d.ts +34 -0
- package/dist/config-center/http-client.js +68 -0
- package/dist/config-center/restart-signal.d.ts +22 -0
- package/dist/config-center/restart-signal.js +39 -0
- package/dist/config-center/skills-mcp.d.ts +20 -1
- package/dist/config-center/skills-mcp.js +42 -7
- package/dist/config-center/types.d.ts +92 -1
- package/dist/config-lkg.d.ts +12 -0
- package/dist/config-lkg.js +41 -0
- package/dist/config-provider.d.ts +78 -0
- package/dist/config-provider.js +165 -2
- package/dist/config-types.d.ts +585 -1
- package/dist/config.d.ts +78 -2
- package/dist/config.js +874 -301
- package/dist/degenerate-instrument.d.ts +38 -0
- package/dist/degenerate-instrument.js +55 -3
- package/dist/elicitation.d.ts +39 -0
- package/dist/elicitation.js +87 -3
- package/dist/env-facts.d.ts +61 -0
- package/dist/env-facts.js +73 -7
- package/dist/fleet/fleet-bus.d.ts +185 -0
- package/dist/fleet/fleet-bus.js +333 -27
- package/dist/fleet/subagent-tail-bus.d.ts +11 -0
- package/dist/fleet/subagent-tail-bus.js +33 -2
- package/dist/fleet-client.d.ts +38 -0
- package/dist/fleet-client.js +44 -9
- package/dist/fleet-lease.d.ts +46 -0
- package/dist/fleet-lease.js +73 -5
- package/dist/hooks/branch-transcript.d.ts +8 -0
- package/dist/hooks/branch-transcript.js +33 -0
- package/dist/hooks/cc-stop-prompt.d.ts +42 -0
- package/dist/hooks/cc-stop-prompt.js +43 -1
- package/dist/hooks/hook-llm.d.ts +15 -0
- package/dist/hooks/hook-llm.js +47 -0
- package/dist/hooks/hook-runner.d.ts +89 -0
- package/dist/hooks/hook-runner.js +327 -18
- package/dist/http/idempotency.d.ts +31 -0
- package/dist/http/idempotency.js +34 -0
- package/dist/http/principal-gate.d.ts +17 -0
- package/dist/http/principal-gate.js +35 -3
- package/dist/http/route-ctx.d.ts +36 -0
- package/dist/http/routes/approvals-assistant.d.ts +25 -0
- package/dist/http/routes/approvals-assistant.js +253 -23
- package/dist/http/routes/attachments.js +22 -4
- package/dist/http/routes/capabilities.d.ts +7 -0
- package/dist/http/routes/capabilities.js +202 -1
- package/dist/http/routes/fleet.d.ts +6 -0
- package/dist/http/routes/fleet.js +94 -5
- package/dist/http/routes/images.d.ts +17 -0
- package/dist/http/routes/images.js +222 -14
- package/dist/http/routes/leader.d.ts +7 -0
- package/dist/http/routes/leader.js +10 -0
- package/dist/http/routes/memory-policy.d.ts +6 -0
- package/dist/http/routes/memory-policy.js +38 -6
- package/dist/http/routes/notify-wake.d.ts +10 -0
- package/dist/http/routes/notify-wake.js +19 -3
- package/dist/http/routes/observability.d.ts +6 -0
- package/dist/http/routes/observability.js +19 -2
- package/dist/http/routes/runs.d.ts +15 -0
- package/dist/http/routes/runs.js +464 -41
- package/dist/http/routes/session-sync.d.ts +15 -0
- package/dist/http/routes/session-sync.js +229 -19
- package/dist/http/routes/sessions-list.d.ts +6 -0
- package/dist/http/routes/sessions-list.js +35 -4
- package/dist/http/routes/sessions.d.ts +14 -0
- package/dist/http/routes/sessions.js +176 -31
- package/dist/http/routes/side-query.d.ts +8 -0
- package/dist/http/routes/side-query.js +26 -1
- package/dist/http/routes/tasks.d.ts +18 -0
- package/dist/http/routes/tasks.js +501 -38
- package/dist/http/routes/trace-usage.d.ts +10 -0
- package/dist/http/routes/trace-usage.js +66 -14
- package/dist/http/routes/workflows.d.ts +12 -0
- package/dist/http/routes/workflows.js +180 -19
- package/dist/http/run-meta.d.ts +11 -0
- package/dist/http/run-meta.js +6 -0
- package/dist/http/send.d.ts +19 -0
- package/dist/http/send.js +11 -0
- package/dist/http/server.d.ts +255 -0
- package/dist/http/server.js +921 -75
- package/dist/http/sse-log.d.ts +15 -0
- package/dist/http/sse-log.js +16 -0
- package/dist/http/tar.d.ts +9 -0
- package/dist/http/tar.js +21 -5
- package/dist/http/wire-gate.d.ts +9 -0
- package/dist/http/wire-gate.js +9 -0
- package/dist/http/wire-types.d.ts +187 -0
- package/dist/http/workspace-content.d.ts +8 -0
- package/dist/http/workspace-content.js +10 -0
- package/dist/images/bake-validate.d.ts +63 -0
- package/dist/images/bake-validate.js +71 -1
- package/dist/images/manifest.d.ts +19 -0
- package/dist/images/manifest.js +6 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +10 -5
- package/dist/key-resolver.d.ts +23 -0
- package/dist/key-resolver.js +27 -2
- package/dist/leader/diffout.d.ts +23 -0
- package/dist/leader/diffout.js +8 -1
- package/dist/leader/diffup.d.ts +32 -0
- package/dist/leader/diffup.js +43 -0
- package/dist/leader/endpoint.d.ts +20 -0
- package/dist/leader/endpoint.js +25 -2
- package/dist/leader/fanout.d.ts +60 -0
- package/dist/leader/fanout.js +29 -3
- package/dist/leader/grader-env-factory.d.ts +74 -0
- package/dist/leader/grader-env-factory.js +62 -3
- package/dist/leader/leader.d.ts +97 -0
- package/dist/leader/leader.js +151 -4
- package/dist/leader/merge.d.ts +94 -0
- package/dist/leader/merge.js +112 -9
- package/dist/leader/planner.d.ts +52 -0
- package/dist/leader/planner.js +47 -3
- package/dist/leader/repair-oracle.d.ts +61 -0
- package/dist/leader/repair-oracle.js +59 -1
- package/dist/leader/repair-wire.d.ts +78 -0
- package/dist/leader/repair-wire.js +79 -2
- package/dist/leader/wire.d.ts +79 -0
- package/dist/leader/wire.js +255 -8
- package/dist/lsp/e2b-bridge.d.ts +16 -0
- package/dist/lsp/e2b-bridge.js +32 -4
- package/dist/lsp/e2b-manager.d.ts +10 -0
- package/dist/lsp/e2b-manager.js +18 -2
- package/dist/lsp/lsp-frames.d.ts +12 -0
- package/dist/lsp/lsp-frames.js +12 -0
- package/dist/lsp/manager.d.ts +12 -0
- package/dist/lsp/manager.js +35 -2
- package/dist/lsp/types.d.ts +10 -0
- package/dist/lsp/ws-transport.d.ts +12 -0
- package/dist/lsp/ws-transport.js +53 -5
- package/dist/lsp-evict.d.ts +14 -0
- package/dist/lsp-evict.js +15 -1
- package/dist/main.js +530 -2129
- package/dist/memory-export.d.ts +1 -0
- package/dist/memory-export.js +4 -0
- package/dist/memory-scope.d.ts +49 -0
- package/dist/memory-scope.js +87 -4
- package/dist/memory-sync-client.d.ts +24 -0
- package/dist/memory-sync-client.js +41 -2
- package/dist/memory-sync.d.ts +23 -0
- package/dist/memory-sync.js +70 -1
- package/dist/model-select.d.ts +39 -0
- package/dist/model-select.js +42 -1
- package/dist/observability/cost-quota.d.ts +20 -0
- package/dist/observability/cost-quota.js +4 -0
- package/dist/observability/cost-taxonomy.d.ts +45 -0
- package/dist/observability/cost-taxonomy.js +34 -0
- package/dist/observability/logger.d.ts +1 -0
- package/dist/observability/logger.js +6 -0
- package/dist/observability/metrics.d.ts +13 -0
- package/dist/observability/metrics.js +63 -0
- package/dist/observability/otel-exporter.d.ts +9 -0
- package/dist/observability/otel-exporter.js +11 -3
- package/dist/observability/principal-context.d.ts +9 -0
- package/dist/observability/principal-context.js +9 -0
- package/dist/observability/prompt-manifest.d.ts +37 -0
- package/dist/observability/prompt-manifest.js +35 -1
- package/dist/observability/rate-limit.d.ts +10 -0
- package/dist/observability/rate-limit.js +1 -0
- package/dist/observability/tool-trace.d.ts +24 -0
- package/dist/observability/tool-trace.js +41 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
- package/dist/orchestration/hardened-vm-runner.js +119 -4
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
- package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
- package/dist/orchestration/hardened-vm-worker.js +27 -0
- package/dist/orchestration/subagent-steer.d.ts +44 -0
- package/dist/orchestration/subagent-steer.js +45 -1
- package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
- package/dist/orchestration/workflow-agent-steer.js +80 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
- package/dist/orchestration/workflow-completion-inbox.js +283 -32
- package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
- package/dist/orchestration/workflow-notify-journal.js +187 -13
- package/dist/parked-decide.d.ts +61 -0
- package/dist/parked-decide.js +58 -1
- package/dist/per-task-image.d.ts +54 -0
- package/dist/per-task-image.js +41 -0
- package/dist/plan-cache-probe.d.ts +35 -0
- package/dist/plan-cache-probe.js +18 -3
- package/dist/plugins/approval-exemption-store.d.ts +7 -0
- package/dist/plugins/approval-exemption-store.js +28 -2
- package/dist/plugins/approval-store-sql.d.ts +64 -0
- package/dist/plugins/approval-store-sql.js +32 -0
- package/dist/plugins/background-agent-store-sql.d.ts +55 -0
- package/dist/plugins/background-agent-store-sql.js +91 -4
- package/dist/plugins/background-shell-support.d.ts +98 -0
- package/dist/plugins/background-shell-support.js +117 -13
- package/dist/plugins/blob-backend.d.ts +104 -0
- package/dist/plugins/blob-backend.js +163 -6
- package/dist/plugins/breaker-state-sql.d.ts +65 -1
- package/dist/plugins/breaker-state-sql.js +46 -8
- package/dist/plugins/caching-session-store.d.ts +42 -0
- package/dist/plugins/caching-session-store.js +63 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
- package/dist/plugins/checkpoint-store-sql.js +239 -11
- package/dist/plugins/file-outcome-sink.d.ts +4 -0
- package/dist/plugins/file-outcome-sink.js +9 -0
- package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
- package/dist/plugins/file-resume-anchor-store.js +43 -4
- package/dist/plugins/file-run-store.d.ts +90 -0
- package/dist/plugins/file-run-store.js +145 -13
- package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
- package/dist/plugins/file-snapshot-store-sql.js +178 -10
- package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
- package/dist/plugins/file-workflow-journal-store.js +10 -0
- package/dist/plugins/fork-routing-session-store.d.ts +47 -0
- package/dist/plugins/fork-routing-session-store.js +51 -3
- package/dist/plugins/host-platform.d.ts +69 -0
- package/dist/plugins/host-platform.js +81 -2
- package/dist/plugins/image-bake-store-sql.d.ts +136 -1
- package/dist/plugins/image-bake-store-sql.js +241 -7
- package/dist/plugins/image-index-sql.d.ts +46 -0
- package/dist/plugins/image-index-sql.js +113 -4
- package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
- package/dist/plugins/k8s-bg-scripts.js +88 -4
- package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
- package/dist/plugins/k8s-exec-protocol.js +41 -0
- package/dist/plugins/local-checkpoint-store.d.ts +40 -0
- package/dist/plugins/local-checkpoint-store.js +86 -7
- package/dist/plugins/local-session-store.d.ts +157 -0
- package/dist/plugins/local-session-store.js +289 -34
- package/dist/plugins/local-task-attachment-store.js +14 -2
- package/dist/plugins/mailbox-store-sql.d.ts +38 -0
- package/dist/plugins/mailbox-store-sql.js +39 -6
- package/dist/plugins/memory-engine-pg.d.ts +30 -0
- package/dist/plugins/memory-engine-pg.js +122 -4
- package/dist/plugins/memory-engine-tidb.d.ts +26 -0
- package/dist/plugins/memory-engine-tidb.js +115 -5
- package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
- package/dist/plugins/memory-engine-vector-util.js +5 -0
- package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
- package/dist/plugins/memory-resume-anchor-store.js +17 -0
- package/dist/plugins/memory-run-store.d.ts +63 -0
- package/dist/plugins/memory-run-store.js +73 -8
- package/dist/plugins/memory-session-policy-store.d.ts +17 -0
- package/dist/plugins/memory-session-policy-store.js +17 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
- package/dist/plugins/memory-sync-store-pg.js +45 -2
- package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
- package/dist/plugins/memory-sync-store-tidb.js +31 -1
- package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
- package/dist/plugins/outcome-ledger-sql.js +97 -3
- package/dist/plugins/pg-approval-store.d.ts +7 -0
- package/dist/plugins/pg-approval-store.js +7 -0
- package/dist/plugins/pg-breaker-state.d.ts +6 -0
- package/dist/plugins/pg-breaker-state.js +6 -0
- package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
- package/dist/plugins/pg-checkpoint-store.js +8 -0
- package/dist/plugins/pg-cost-quota.d.ts +17 -0
- package/dist/plugins/pg-cost-quota.js +6 -0
- package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/pg-file-snapshot-store.js +6 -0
- package/dist/plugins/pg-image-bake.d.ts +9 -0
- package/dist/plugins/pg-image-bake.js +9 -0
- package/dist/plugins/pg-image-index.d.ts +9 -0
- package/dist/plugins/pg-image-index.js +9 -0
- package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
- package/dist/plugins/pg-outcome-ledger.js +9 -0
- package/dist/plugins/pg-pool.d.ts +50 -0
- package/dist/plugins/pg-pool.js +78 -0
- package/dist/plugins/pg-query.d.ts +11 -0
- package/dist/plugins/pg-rate-limiter.d.ts +23 -0
- package/dist/plugins/pg-rate-limiter.js +12 -2
- package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/pg-resume-anchor-store.js +5 -0
- package/dist/plugins/pg-run-store.d.ts +7 -0
- package/dist/plugins/pg-run-store.js +7 -0
- package/dist/plugins/pg-safe-json.d.ts +13 -0
- package/dist/plugins/pg-safe-json.js +40 -4
- package/dist/plugins/pg-session-policy-store.d.ts +5 -0
- package/dist/plugins/pg-session-policy-store.js +5 -0
- package/dist/plugins/pg-session-storage.d.ts +72 -0
- package/dist/plugins/pg-session-storage.js +152 -20
- package/dist/plugins/pg-session-store.d.ts +10 -0
- package/dist/plugins/pg-session-store.js +10 -0
- package/dist/plugins/pg-tool-result-store.d.ts +7 -0
- package/dist/plugins/pg-tool-result-store.js +7 -0
- package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-journal-store.js +7 -0
- package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-run-store.js +7 -0
- package/dist/plugins/posix-shell-fs.d.ts +3 -0
- package/dist/plugins/posix-shell-fs.js +31 -1
- package/dist/plugins/remote-env-adb.d.ts +25 -0
- package/dist/plugins/remote-env-adb.js +95 -12
- package/dist/plugins/remote-env-e2b.d.ts +146 -0
- package/dist/plugins/remote-env-e2b.js +371 -40
- package/dist/plugins/remote-env-file-error.d.ts +34 -0
- package/dist/plugins/remote-env-file-error.js +37 -0
- package/dist/plugins/remote-env-host.d.ts +151 -0
- package/dist/plugins/remote-env-host.js +468 -70
- package/dist/plugins/remote-env-k8s.d.ts +135 -0
- package/dist/plugins/remote-env-k8s.js +318 -32
- package/dist/plugins/remote-env-local-docker.d.ts +65 -0
- package/dist/plugins/remote-env-local-docker.js +149 -24
- package/dist/plugins/remote-env-ssh.d.ts +35 -0
- package/dist/plugins/remote-env-ssh.js +117 -20
- package/dist/plugins/remote-scratchpad.d.ts +38 -0
- package/dist/plugins/remote-scratchpad.js +32 -2
- package/dist/plugins/remote-shell.d.ts +22 -0
- package/dist/plugins/remote-shell.js +27 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
- package/dist/plugins/resume-anchor-store-sql.js +11 -0
- package/dist/plugins/roster-store-sql.d.ts +27 -0
- package/dist/plugins/roster-store-sql.js +54 -0
- package/dist/plugins/run-store-sql.d.ts +194 -0
- package/dist/plugins/run-store-sql.js +210 -9
- package/dist/plugins/s3-presign.d.ts +20 -0
- package/dist/plugins/s3-presign.js +49 -2
- package/dist/plugins/scheduler-support.d.ts +12 -0
- package/dist/plugins/scheduler-support.js +75 -3
- package/dist/plugins/send-file-ledger.d.ts +15 -0
- package/dist/plugins/send-file-ledger.js +53 -4
- package/dist/plugins/send-user-file.d.ts +77 -0
- package/dist/plugins/send-user-file.js +92 -4
- package/dist/plugins/session-policy-store-sql.d.ts +15 -0
- package/dist/plugins/session-policy-store-sql.js +75 -3
- package/dist/plugins/session-store.d.ts +45 -0
- package/dist/plugins/session-store.js +51 -0
- package/dist/plugins/sql-driver.d.ts +77 -0
- package/dist/plugins/sql-driver.js +4 -0
- package/dist/plugins/sql-escape.d.ts +8 -0
- package/dist/plugins/sql-escape.js +8 -0
- package/dist/plugins/sql-row-helpers.d.ts +25 -0
- package/dist/plugins/sql-row-helpers.js +25 -0
- package/dist/plugins/store-backend.d.ts +103 -0
- package/dist/plugins/store-backend.js +120 -27
- package/dist/plugins/store-contracts.d.ts +62 -0
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +60 -0
- package/dist/plugins/task-attachment-store.js +49 -3
- package/dist/plugins/task-list-store-sql.d.ts +25 -0
- package/dist/plugins/task-list-store-sql.js +21 -0
- package/dist/plugins/tidb-approval-store.d.ts +6 -0
- package/dist/plugins/tidb-approval-store.js +6 -0
- package/dist/plugins/tidb-breaker-state.d.ts +5 -0
- package/dist/plugins/tidb-breaker-state.js +5 -0
- package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
- package/dist/plugins/tidb-checkpoint-store.js +7 -0
- package/dist/plugins/tidb-cost-quota.d.ts +6 -0
- package/dist/plugins/tidb-cost-quota.js +1 -0
- package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/tidb-file-snapshot-store.js +6 -0
- package/dist/plugins/tidb-image-bake.d.ts +8 -0
- package/dist/plugins/tidb-image-bake.js +8 -0
- package/dist/plugins/tidb-image-index.d.ts +8 -0
- package/dist/plugins/tidb-image-index.js +8 -0
- package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
- package/dist/plugins/tidb-outcome-ledger.js +10 -0
- package/dist/plugins/tidb-pool.d.ts +56 -0
- package/dist/plugins/tidb-pool.js +181 -1
- package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
- package/dist/plugins/tidb-rate-limiter.js +5 -2
- package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/tidb-resume-anchor-store.js +5 -0
- package/dist/plugins/tidb-run-store.d.ts +7 -0
- package/dist/plugins/tidb-run-store.js +7 -0
- package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
- package/dist/plugins/tidb-session-policy-store.js +5 -0
- package/dist/plugins/tidb-session-storage.d.ts +43 -0
- package/dist/plugins/tidb-session-storage.js +62 -3
- package/dist/plugins/tidb-session-store.d.ts +142 -0
- package/dist/plugins/tidb-session-store.js +264 -16
- package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
- package/dist/plugins/tidb-tool-result-store.js +7 -0
- package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/tidb-workflow-journal-store.js +7 -0
- package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
- package/dist/plugins/tidb-workflow-run-store.js +8 -0
- package/dist/plugins/tool-result-store-sql.d.ts +58 -0
- package/dist/plugins/tool-result-store-sql.js +38 -2
- package/dist/plugins/web-search.d.ts +35 -0
- package/dist/plugins/web-search.js +45 -9
- package/dist/plugins/workflow-journal-limits.d.ts +10 -0
- package/dist/plugins/workflow-journal-limits.js +10 -0
- package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
- package/dist/plugins/workflow-journal-store-sql.js +58 -2
- package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
- package/dist/plugins/workflow-run-store-sql.js +84 -6
- package/dist/plugins/worktree-isolation.d.ts +45 -0
- package/dist/plugins/worktree-isolation.js +105 -6
- package/dist/plugins/write-behind-counter.d.ts +56 -1
- package/dist/plugins/write-behind-counter.js +53 -14
- package/dist/principal-jwt.d.ts +24 -0
- package/dist/principal-jwt.js +60 -5
- package/dist/project-memory.d.ts +22 -0
- package/dist/project-memory.js +144 -15
- package/dist/prompts-domain-validate.d.ts +28 -0
- package/dist/prompts-domain-validate.js +42 -1
- package/dist/question.d.ts +33 -0
- package/dist/question.js +69 -2
- package/dist/resource-suspend.d.ts +21 -0
- package/dist/resource-suspend.js +16 -0
- package/dist/router/route-orchestration.d.ts +78 -0
- package/dist/router/route-orchestration.js +77 -0
- package/dist/run-local.d.ts +32 -0
- package/dist/run-local.js +172 -8
- package/dist/runs.d.ts +189 -4
- package/dist/runs.js +465 -24
- package/dist/runtime-caps-resolver.d.ts +106 -0
- package/dist/runtime-caps-resolver.js +89 -4
- package/dist/runtime-governance.d.ts +84 -0
- package/dist/runtime-governance.js +127 -1
- package/dist/sandbox-pkg-source.d.ts +23 -0
- package/dist/sandbox-pkg-source.js +37 -0
- package/dist/sealed-key.d.ts +54 -0
- package/dist/sealed-key.js +68 -3
- package/dist/security.d.ts +108 -0
- package/dist/security.js +145 -6
- package/dist/sema-registry.d.ts +21 -0
- package/dist/sema-registry.js +21 -0
- package/dist/session-leaf-bus.d.ts +31 -0
- package/dist/session-leaf-bus.js +32 -0
- package/dist/session-sync-content.d.ts +46 -0
- package/dist/session-sync-content.js +47 -1
- package/dist/session-sync-kernel.d.ts +89 -0
- package/dist/session-sync-kernel.js +48 -3
- package/dist/session-sync.d.ts +125 -0
- package/dist/session-sync.js +181 -8
- package/dist/session-titler.d.ts +26 -0
- package/dist/session-titler.js +41 -7
- package/dist/session-watch.d.ts +53 -1
- package/dist/session-watch.js +73 -9
- package/dist/sighup-idle.d.ts +30 -0
- package/dist/sighup-idle.js +12 -1
- package/dist/spec-fields.d.ts +91 -3
- package/dist/spec-fields.js +116 -4
- package/dist/task-cwd.d.ts +50 -0
- package/dist/task-cwd.js +68 -1
- package/dist/task-mcp.d.ts +47 -0
- package/dist/task-mcp.js +29 -0
- package/dist/task-settings.d.ts +175 -0
- package/dist/task-settings.js +226 -11
- package/dist/task-workflow.d.ts +67 -0
- package/dist/task-workflow.js +75 -8
- package/dist/tool-approval.d.ts +91 -0
- package/dist/tool-approval.js +215 -0
- package/dist/trace/artifacts.d.ts +9 -0
- package/dist/trace/artifacts.js +30 -5
- package/dist/trace/core-keyset-guard.d.ts +18 -0
- package/dist/trace/ledger-sink.d.ts +43 -0
- package/dist/trace/ledger-sink.js +64 -5
- package/dist/trace/project.d.ts +133 -0
- package/dist/trace/project.js +189 -2
- package/dist/trace/redact.d.ts +19 -0
- package/dist/trace/redact.js +66 -9
- package/dist/usage-analytics.d.ts +26 -0
- package/dist/usage-analytics.js +26 -3
- package/package.json +1 -1
package/dist/leader/wire.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2 MVP M4 — leader endpoint wiring (V2-MVP-PLAN.md). `createLeaderRunner` turns a LeaderRequestBody into a
|
|
3
|
+
* `runLeaderTask` invocation with REAL deps: per-worker E2B envs (leader-owned, static so they outlive the
|
|
4
|
+
* task for diff-out) + a real ephemeral E2B integration sandbox + the Coordinator's credentialed
|
|
5
|
+
* `git push --force-with-lease`. This is the productization of the joint dogfood (which validated the exact
|
|
6
|
+
* logic on real infra) — gated behind LEADER_ENABLED (default off).
|
|
7
|
+
*
|
|
8
|
+
* 🔴 DEPLOY REQUIREMENTS (document — not satisfied by the default bun-slim image): the control plane (service
|
|
9
|
+
* host) needs **git** on PATH for the Coordinator clone/apply/push, plus a reachable durable remote +
|
|
10
|
+
* write creds (LEADER_GIT_TOKEN). E2B workers need outbound net only if the base repo is cloned over the
|
|
11
|
+
* network; the MVP seeds the base from the Coordinator (no worker→remote net). MVP Planner = caller-provided
|
|
12
|
+
* `subtasks` (an LLM DAG-planner is a follow-up).
|
|
13
|
+
*/
|
|
1
14
|
import { execFileSync } from "node:child_process";
|
|
2
15
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
16
|
import { join } from "node:path";
|
|
@@ -11,6 +24,12 @@ import { pullDiff, safeRev } from "./diffout.js";
|
|
|
11
24
|
import { runLeaderTask } from "./leader.js";
|
|
12
25
|
import { attachRepairLoopDeps } from "./repair-wire.js";
|
|
13
26
|
import { routePlanWithFallback, validateSubtasks } from "./planner.js";
|
|
27
|
+
/** The single-agent `runRepairLoop` is now WIRED LIVE (the canary-enable slice): when `LEADER_REPAIR_LOOP=true`
|
|
28
|
+
* the wire provisions a DEDICATED oracle-seeded grader sandbox per solo worker and attaches a real async
|
|
29
|
+
* `resolve` to `attachRepairLoopDeps` (below). With this `true`, flipping `LEADER_REPAIR_LOOP` engages BOTH the
|
|
30
|
+
* repair loop AND the §10.5 resource-suspend mutual exclusion (a repair-owned worker never resource-suspends).
|
|
31
|
+
* Still OFF-by-default — with the flag off, `resolve` is undefined → `attachRepairLoopDeps` is a no-op → the
|
|
32
|
+
* default single-agent path is byte-identical to today. */
|
|
14
33
|
const REPAIR_LOOP_WIRED = true;
|
|
15
34
|
const sh = (env) => async (cmd) => {
|
|
16
35
|
const r = await env.exec(`bash -lc ${JSON.stringify(cmd)}`);
|
|
@@ -28,30 +47,77 @@ const asIntegrationEnv = (env) => ({
|
|
|
28
47
|
writeFile: async (p, c) => { const r = await env.writeFile(p, c); if (!r.ok)
|
|
29
48
|
throw r.error; },
|
|
30
49
|
});
|
|
50
|
+
/**
|
|
51
|
+
* Resume-safe worker staging (the design/68 F2(a) factory-env path). Runs adapter-side before the agent's
|
|
52
|
+
* first workspace-touching call: seed the base repo at the worker branch + plant the upload script (so the
|
|
53
|
+
* presigned URL never passes through the model).
|
|
54
|
+
*
|
|
55
|
+
* 🔴 BL-1 fix (design/74 Slice 6): on a RESOURCE-SUSPEND RESUME core re-invokes the `executionEnvFactory`,
|
|
56
|
+
* producing a FRESH `withStaging` wrapper (`staged=undefined`) whose `stage()` runs AGAIN — AFTER core's
|
|
57
|
+
* `resumeVM()` has already untar'd the snapshot onto the fresh pod (`resumeVM` is not a STAGED_METHOD, so it
|
|
58
|
+
* is NOT intercepted by the staging proxy; the agent's first `exec` is what triggers `stage()`, lazily, and
|
|
59
|
+
* by then the snapshot is restored). The old `stage()` ran the seed UNCONDITIONALLY:
|
|
60
|
+
* `${seedCmd}; cd ${repo}; git checkout -q -b ${branch}`
|
|
61
|
+
* and `seedCmd` begins with `rm -rf /workspace/repo` — so it WIPED the just-restored snapshot and re-seeded at
|
|
62
|
+
* `baseSha`, then created the worker branch at base. The forensic proof (leaderRunId 019ecda7): the suspend
|
|
63
|
+
* snapshot object DID contain the worker's commit (`git log` in the S3 tarball = the real progress), yet every
|
|
64
|
+
* resumed slice's `git log` showed only the base commit — the worker rebuilt destroyed work for ~47 min. THIS
|
|
65
|
+
* (a staging re-seed clobbering a correctly-restored snapshot) is the dominant cause of failed make-real runs.
|
|
66
|
+
*
|
|
67
|
+
* The fix = a RESTORED-SNAPSHOT SENTINEL that no-ops staging on resume. The robust signal is the upload-script
|
|
68
|
+
* MARKER FILE (`uploadScriptPath`): staging itself plants it, so it is present in EVERY restored snapshot
|
|
69
|
+
* (verified: it survives in both a base-state in-progress snapshot AND a post-commit one) and ABSENT on a
|
|
70
|
+
* genuinely fresh pod — and it is INDEPENDENT of git/commit state. That last point matters: a worker can
|
|
71
|
+
* suspend with work in progress but no commit yet (HEAD still == baseSha), so a "HEAD advanced past baseSha"
|
|
72
|
+
* probe alone would WRONGLY re-seed+clobber that valid snapshot. The marker captures "staging already ran here"
|
|
73
|
+
* regardless of whether a commit landed. We additionally accept the worker branch already existing as a
|
|
74
|
+
* secondary restored-snapshot signal (belt-and-suspenders for the same git-state-independent reason).
|
|
75
|
+
*
|
|
76
|
+
* A FRESH pod has neither marker nor branch → full staging runs. A probe transport failure falls through to
|
|
77
|
+
* full staging too (fails honestly via `sh()`, never silently skips). `branch`/paths are `validateSubtasks`-
|
|
78
|
+
* clean / deployment config and are JSON-quoted under `bash -lc` regardless. Exported for the regression test.
|
|
79
|
+
*/
|
|
31
80
|
export async function stageWorkerEnv(env, opts) {
|
|
32
81
|
const { seedCmd, repo, branch, uploadScriptPath, uploadScript } = opts;
|
|
82
|
+
// Restored-snapshot sentinel (non-throwing exec — we need the exit code, not an exception). Two independent
|
|
83
|
+
// signals, EITHER of which proves "staging already ran here, this is a resumed snapshot, do NOT re-seed":
|
|
84
|
+
// (1) the upload-script marker file is present — the definitive signal (planted by staging, git-state
|
|
85
|
+
// independent, so it covers an in-progress-but-uncommitted snapshot where HEAD is still at base); and
|
|
86
|
+
// (2) the worker branch already exists — secondary, also git-state independent.
|
|
87
|
+
// Both probed in ONE round-trip; exit 0 ⇒ restored snapshot ⇒ NO-OP (never `rm -rf` the restored workspace).
|
|
88
|
+
// A transport failure ({ok:false}) falls through to full staging (honest fail via sh()), never silent-skips.
|
|
33
89
|
const probe = await env.exec(`bash -lc ${JSON.stringify(`if [ -f ${uploadScriptPath} ]; then exit 0; fi; ` +
|
|
34
90
|
`cd ${repo} 2>/dev/null && git rev-parse --verify --quiet refs/heads/${branch} >/dev/null && exit 0; ` +
|
|
35
91
|
`exit 1`)}`);
|
|
36
92
|
if (probe.ok && probe.value.exitCode === 0)
|
|
37
|
-
return;
|
|
93
|
+
return; // resume — repo/branch/upload-script already in the snapshot
|
|
38
94
|
await sh(env)(`${seedCmd}; cd ${repo}; git checkout -q -b ${branch}`);
|
|
39
95
|
const wr = await env.writeFile(uploadScriptPath, uploadScript);
|
|
40
96
|
if (!wr.ok)
|
|
41
97
|
throw new Error(`upload-script staging failed: ${wr.error.message}`);
|
|
42
98
|
}
|
|
99
|
+
/** Build the `runLeader(body)` the HTTP endpoint invokes. Constructs real per-task deps + runs the leader. */
|
|
100
|
+
/**
|
|
101
|
+
* Per-leader-run resource bounds derived from env (2026-06-14). Exported for unit tests. The worker sandbox
|
|
102
|
+
* lifetime (BUG2), the worker's diff-upload presigned-URL TTL (BUG1), and the worker spec's triple bound
|
|
103
|
+
* (maxTurns/timeoutSec/maxCostUsd, #15) ALL track one `leaderTimeoutMs` — a hardcoded 10min (sandbox) or 1h
|
|
104
|
+
* (URL) silently killed long autonomous builds or expired the diff upload mid-run. core's turn cap is now a
|
|
105
|
+
* high net (10000), so the leader gives each worker an explicit triple bound; a sub-task's own limits override.
|
|
106
|
+
*/
|
|
43
107
|
export function leaderResourceConfig(env = process.env) {
|
|
44
|
-
const leaderTimeoutMs = Math.max(600_000, Math.floor(Number(env.LEADER_TIMEOUT_MS ?? "0")) || 86_400_000);
|
|
108
|
+
const leaderTimeoutMs = Math.max(600_000, Math.floor(Number(env.LEADER_TIMEOUT_MS ?? "0")) || 86_400_000); // default 24h (was 10min)
|
|
45
109
|
const workerMaxTurns = Math.floor(Number(env.LEADER_WORKER_MAX_TURNS ?? "0")) || 10_000;
|
|
46
110
|
const workerBudgetUsd = Number(env.LEADER_WORKER_BUDGET_USD ?? "0") || 100;
|
|
47
111
|
const resourceSuspendOn = String(env.LEADER_RESOURCE_SUSPEND ?? "").toLowerCase() === "true";
|
|
112
|
+
// Per-slice window: a fraction of the total so a worker suspends+resumes several times across its budget
|
|
113
|
+
// (default = total/4, min $1). Smaller window ⇒ more, shorter slices ⇒ progress saved more often.
|
|
48
114
|
const sliceMaxCostUsd = Number(env.LEADER_WORKER_SLICE_BUDGET_USD ?? "0") || Math.max(1, workerBudgetUsd / 4);
|
|
49
115
|
return {
|
|
50
116
|
leaderTimeoutMs,
|
|
51
117
|
workerMaxTurns,
|
|
52
118
|
workerBudgetUsd,
|
|
53
119
|
workerLimits: { limits: { maxTurns: workerMaxTurns, timeoutSec: Math.floor(leaderTimeoutMs / 1000) }, maxCostUsd: workerBudgetUsd },
|
|
54
|
-
presignTtlSec: Math.ceil(leaderTimeoutMs / 1000) + 600,
|
|
120
|
+
presignTtlSec: Math.ceil(leaderTimeoutMs / 1000) + 600, // URL/sandbox must outlive the worker (BUG1/BUG2)
|
|
55
121
|
...(resourceSuspendOn
|
|
56
122
|
? {
|
|
57
123
|
resourceSuspend: {
|
|
@@ -71,23 +137,42 @@ export function createLeaderRunner(cfg) {
|
|
|
71
137
|
const repairRounds = Math.max(0, Math.floor(Number(process.env.LEADER_REPAIR_ROUNDS ?? cfg.repairRounds ?? 0)) || 0);
|
|
72
138
|
const repairBudgetUsd = Number(process.env.LEADER_REPAIR_BUDGET_USD ?? "4") || 4;
|
|
73
139
|
const conflictRounds = Math.max(0, Math.floor(Number(process.env.LEADER_CONFLICT_ROUNDS ?? cfg.conflictRounds ?? 0)) || 0);
|
|
140
|
+
// ── LEADER-REPAIRLOOP-INTEGRATION §10 env knobs (FRESH hunk, §10.8 — mirrors LEADER_REPAIR_ROUNDS above) ──
|
|
141
|
+
// Every flag default-OFF so the whole feature is inert until flipped on a canary (the default path is
|
|
142
|
+
// byte-identical to today). `LEADER_REPAIR_LOOP` is the MASTER (gates the single-agent `runRepairLoop` dep);
|
|
143
|
+
// `LEADER_MEASURE_GATES` gates the merge push-hold-on-signal + measure-drives-repair (§10.3/§10.4);
|
|
144
|
+
// `LEADER_REPAIR_LOOP_ATTEMPTS` is the in-loop attempt ceiling (validated 2-3, default 2 — design/78 §5);
|
|
145
|
+
// `LEADER_ORACLE_FLAKY_K` is the flaky-settle re-isolation count (default 2 — §10.1 / repair-oracle.ts).
|
|
74
146
|
const repairLoopOn = String(process.env.LEADER_REPAIR_LOOP ?? "").toLowerCase() === "true";
|
|
75
147
|
const measureGatesOn = String(process.env.LEADER_MEASURE_GATES ?? "").toLowerCase() === "true";
|
|
76
148
|
const repairLoopAttempts = Math.min(3, Math.max(2, Math.floor(Number(process.env.LEADER_REPAIR_LOOP_ATTEMPTS ?? "2")) || 2));
|
|
77
149
|
const oracleFlakyK = Math.max(1, Math.floor(Number(process.env.LEADER_ORACLE_FLAKY_K ?? "2")) || 2);
|
|
150
|
+
// worker resource bounds (limits/maxCostUsd) + presign ttl are derived in leaderResourceConfig(), above.
|
|
151
|
+
// Bounded integration-repair (search 2026-06-14): when the merged tree compiles-clean-but-fails, run a strong
|
|
152
|
+
// agent WITH HANDS in the live merged sandbox to fix the cross-worker integration, then mergeBranches re-runs
|
|
153
|
+
// testCmd. OFF unless LEADER_REPAIR_ROUNDS>0 — closes over the RAW env (hands need the real RemoteExecutionEnv,
|
|
154
|
+
// not the exec/writeFile-only IntegrationEnv wrapper). Strong model (default role); no durable wiring (short).
|
|
78
155
|
const mkRepair = (rawEnv, repoDir, oracleFiles) => {
|
|
79
156
|
if (repairRounds <= 0)
|
|
80
157
|
return undefined;
|
|
81
158
|
return {
|
|
82
159
|
maxRounds: repairRounds,
|
|
83
160
|
run: async ({ round, errorText, testCmd }) => {
|
|
161
|
+
// 🔴 Measurement integrity (council blocker + partner-Codex gotcha): HIDE the hidden oracle so the repair
|
|
162
|
+
// agent (rooted at the repo) can't `cat` the test it's graded on and cheat; RE-INJECT it in `finally` so
|
|
163
|
+
// merge's re-test gate verifies the fix against the real oracle (and it's hidden again next round).
|
|
84
164
|
for (const f of oracleFiles) {
|
|
85
|
-
await rawEnv.remove(f.path).catch(() => { });
|
|
165
|
+
await rawEnv.remove(f.path).catch(() => { }); // best-effort delete (may be absent)
|
|
166
|
+
// FAIL-CLOSED (partner-Codex): remove() returns a Result that does NOT throw on failure, so a silent
|
|
167
|
+
// {ok:false} would leave the oracle readable and the repair model could `cat` it. VERIFY it's gone.
|
|
86
168
|
const ex = await rawEnv.exists(f.path);
|
|
87
169
|
if (ex.ok && ex.value)
|
|
88
170
|
throw new Error(`oracle still present after remove (${f.path}) — refusing repair (measurement integrity)`);
|
|
89
171
|
}
|
|
90
172
|
try {
|
|
173
|
+
// rootPath: repoDir (Codex review #4) — without it core roots the file tools at executionEnv.cwd
|
|
174
|
+
// (/workspace on Kata), one level above the repo (/workspace/repo). bash can cd, but the dedicated
|
|
175
|
+
// read/edit tools would start too high + lose containment.
|
|
91
176
|
const runner = new Runner({ brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing, executionEnv: rawEnv, rootPath: repoDir });
|
|
92
177
|
const objective = [
|
|
93
178
|
`The integrated project at ${repoDir} fails its build/test. Make the MINIMAL change to the working tree so this command exits 0 (cd into the repo and run it yourself to confirm):`,
|
|
@@ -95,6 +180,8 @@ export function createLeaderRunner(cfg) {
|
|
|
95
180
|
`Several agents each ported a DISJOINT module group; the failure is almost certainly a cross-module integration mismatch (a shared interface, a missing/renamed symbol, a type/signature disagreement between two groups). Read the failing files, fix the smallest set of files, and re-run the command to verify it passes.`,
|
|
96
181
|
`HARD RULES: do NOT git commit or git push; do NOT modify build configuration (gradle.properties / AGP / dependency versions / settings); do NOT add build-tooling files; do NOT call AskUserQuestion — decide autonomously. Preserve the ported semantics — fix the integration, never delete behavior just to make it pass.`,
|
|
97
182
|
``,
|
|
183
|
+
// BL-32 — the failing output is worker/build-authored; delimit it so an injected instruction in a stack
|
|
184
|
+
// trace / test message can't steer the repair agent (design/53 trifecta).
|
|
98
185
|
delimitUntrusted("FAILING OUTPUT (untrusted)", errorText),
|
|
99
186
|
].join("\n");
|
|
100
187
|
const res = await runner
|
|
@@ -105,11 +192,16 @@ export function createLeaderRunner(cfg) {
|
|
|
105
192
|
limits: { timeoutSec: Math.max(300, Math.floor(leaderTimeoutMs / 1000 / 2)) },
|
|
106
193
|
})
|
|
107
194
|
.result();
|
|
195
|
+
// A non-completed repair (timeout/abort) may leave a process alive in the SAME Kata pod that would race
|
|
196
|
+
// the merge re-test (Codex review #1) — surface it as a throw so mergeBranches does NOT re-test: it keeps
|
|
197
|
+
// the original failure and the `finally` destroys the sandbox, killing any orphan.
|
|
108
198
|
if (res.status !== "completed")
|
|
109
199
|
throw new Error(`repair round ${round} did not complete (status=${res.status})`);
|
|
110
200
|
return { costUsd: res.stats?.costMicroUsd !== undefined ? res.stats.costMicroUsd / 1e6 : undefined, note: res.result?.slice(0, 200) };
|
|
111
201
|
}
|
|
112
202
|
finally {
|
|
203
|
+
// Re-inject the oracle so merge's re-test gate (run right after) verifies the fix against the REAL hidden
|
|
204
|
+
// test — even if the repair model threw. It's hidden again at the top of the next round.
|
|
113
205
|
for (const f of oracleFiles) {
|
|
114
206
|
const wr = await rawEnv.writeFile(f.path, f.content);
|
|
115
207
|
if (!wr.ok)
|
|
@@ -119,6 +211,12 @@ export function createLeaderRunner(cfg) {
|
|
|
119
211
|
},
|
|
120
212
|
};
|
|
121
213
|
};
|
|
214
|
+
// Bounded merge-conflict resolution (search 2026-06-16): a `git apply --3way` conflict means two workers touched
|
|
215
|
+
// overlapping lines. Instead of the leader discarding ALL fan-out work + redoing single (collapseToSingle), run a
|
|
216
|
+
// strong agent WITH HANDS in the conflicted sandbox to integrate the conflicting worker's patch (the others
|
|
217
|
+
// already applied clean). OFF unless LEADER_CONFLICT_ROUNDS>0. Mirrors mkRepair: raw env for hands; hide the
|
|
218
|
+
// hidden oracle so the resolver can't grade-peek; restore in `finally` so the downstream test gate sees the real
|
|
219
|
+
// oracle. mergeBranches re-checks for leftover markers/.rej and degrades to collapse if the resolution is unclean.
|
|
122
220
|
const mkConflictResolver = (rawEnv, repoDir, oracleFiles) => {
|
|
123
221
|
if (conflictRounds <= 0)
|
|
124
222
|
return undefined;
|
|
@@ -139,6 +237,8 @@ export function createLeaderRunner(cfg) {
|
|
|
139
237
|
`When done, NO conflict markers and NO *.rej files may remain under ${repoDir}. Verify yourself before finishing: grep -rIlE '^(<<<<<<<|>>>>>>>)' . ; find . -name '*.rej' — BOTH must print nothing.`,
|
|
140
238
|
`HARD RULES: do NOT git commit / git add / git push (the coordinator squashes at the end); do NOT modify build configuration; do NOT call AskUserQuestion — decide autonomously. Preserve both sides' ported semantics.`,
|
|
141
239
|
``,
|
|
240
|
+
// BL-32 — the worker patch + conflict text are untrusted worker-adjacent content; delimit both so an
|
|
241
|
+
// injected instruction can't steer the conflict-resolver agent (design/53 trifecta).
|
|
142
242
|
delimitUntrusted("CONFLICTING WORKER PATCH (untrusted)", patch.slice(0, 6000)),
|
|
143
243
|
delimitUntrusted("CONFLICT DETAILS (untrusted)", conflictText),
|
|
144
244
|
].join("\n");
|
|
@@ -169,12 +269,22 @@ export function createLeaderRunner(cfg) {
|
|
|
169
269
|
if (!body.objective || !body.durableRemote || !body.testCmd || !body.seedCmd || !body.baseSha) {
|
|
170
270
|
return { ok: false, reports: [], cancelled: false, error: "request must provide objective, durableRemote, baseSha, testCmd, seedCmd" };
|
|
171
271
|
}
|
|
272
|
+
// `durableRemote` is handed to `git clone` on the CONTROL PLANE (with the Coordinator's creds). git executes
|
|
273
|
+
// transport-helper URLs (`ext::sh -c '…'`, `file://…`) as commands, so allow only a normal http(s)/git/ssh
|
|
274
|
+
// URL or an scp-style user@host:path — reject the transport-helper class even though the caller is trusted.
|
|
172
275
|
if (!/^(?:https?|git|ssh):\/\/[^\s]+$/i.test(body.durableRemote) && !/^[\w.-]+@[\w.-]+:[^\s]+$/.test(body.durableRemote)) {
|
|
173
276
|
return { ok: false, reports: [], cancelled: false, error: "durableRemote must be an http(s)/git/ssh URL or user@host:path (no ext::/file:// transport helpers)" };
|
|
174
277
|
}
|
|
278
|
+
// baseSha is interpolated into worker-shell lines on BOTH env paths (static: format-patch via pullDiff,
|
|
279
|
+
// which re-validates; factory: the staged upload script) — gate it here so the factory path is covered too.
|
|
175
280
|
if (!safeRev(body.baseSha)) {
|
|
176
281
|
return { ok: false, reports: [], cancelled: false, error: "baseSha must be a plain git rev (sha/branch token)" };
|
|
177
282
|
}
|
|
283
|
+
// B-2: write the hidden oracle into the integration sandbox (workers never see it) + local-exclude it so the
|
|
284
|
+
// squash `git add -A` does NOT commit/push it into the durable integration branch (Codex review #1: else the
|
|
285
|
+
// hidden test leaks into the repo, visible to any future worker seeded from it). gradle compiles src/test
|
|
286
|
+
// regardless of git status, so the correctness gate still runs. NOTE: if integration-repair is enabled, the
|
|
287
|
+
// repair agent (rooted at the repo) could still READ the on-disk oracle — delete it before repair runs then.
|
|
178
288
|
const injectOracles = async (env) => {
|
|
179
289
|
const ofs = body.oracleFiles ?? [];
|
|
180
290
|
if (ofs.length === 0)
|
|
@@ -184,6 +294,9 @@ export function createLeaderRunner(cfg) {
|
|
|
184
294
|
if (!wr.ok)
|
|
185
295
|
throw wr.error;
|
|
186
296
|
}
|
|
297
|
+
// Local-exclude each oracle so `git add -A` never commits it (B-2 sandbox-only). Root-anchor with a leading
|
|
298
|
+
// "/" + escape a leading "#"/"!" so the path is a literal exclude, not a gitignore comment/negation (council
|
|
299
|
+
// #4). APPEND to (don't clobber) any seed-configured excludes — read the current file first (council #3).
|
|
187
300
|
const anchor = (p) => "/" + (/^[#!]/.test(p) ? "\\" + p : p);
|
|
188
301
|
const rel = ofs.map((f) => anchor(f.path.startsWith(`${repo}/`) ? f.path.slice(repo.length + 1) : f.path)).join("\n");
|
|
189
302
|
const cur = await env.exec(`bash -lc ${JSON.stringify(`cat ${repo}/.git/info/exclude 2>/dev/null || true`)}`);
|
|
@@ -192,8 +305,18 @@ export function createLeaderRunner(cfg) {
|
|
|
192
305
|
if (!ex.ok)
|
|
193
306
|
throw ex.error;
|
|
194
307
|
};
|
|
308
|
+
// design/158 A13: the four LeaderDeps methods below (plan/provisionWorker/provisionIntegrationSandbox/push)
|
|
309
|
+
// are named local functions — same closure scope, same capture, same execution order as when they were
|
|
310
|
+
// inline object-literal properties; only the "anonymous inline closure" form changed (behavior identical).
|
|
311
|
+
// caller-provided sub-tasks = an explicit FAN-OUT override; else the difficulty ROUTER decides (one model
|
|
312
|
+
// completion): default single (a 1-subtask plan) and only fan out when clearly+economically decomposable
|
|
313
|
+
// Either way → VALIDATED disjoint-file sub-tasks (planner.ts enforces the Coordinator's invariant).
|
|
195
314
|
const plan = async () => {
|
|
196
315
|
if (Array.isArray(body.subtasks) && body.subtasks.length > 0) {
|
|
316
|
+
// Validate caller-supplied sub-tasks through the SAME deterministic checks as an LLM plan — the
|
|
317
|
+
// branch is interpolated into a worker-container shell command (planner.validateSubtasks rejects a
|
|
318
|
+
// shell-unsafe branch / leading "-" / "..") and the disjoint-file + unique-id invariants are what
|
|
319
|
+
// the Coordinator's parallel merge relies on. Was a straight map() that skipped all of it.
|
|
197
320
|
return validateSubtasks(body.subtasks);
|
|
198
321
|
}
|
|
199
322
|
const planRunner = new Runner({ brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing });
|
|
@@ -201,10 +324,14 @@ export function createLeaderRunner(cfg) {
|
|
|
201
324
|
const res = await planRunner.runTaskStream({
|
|
202
325
|
objective: prompt,
|
|
203
326
|
sessionId: `leader-route-${Date.now()}`,
|
|
327
|
+
// Pin the route to a cheap classifier model (see `routerModel` doc): the heavy reasoning model
|
|
328
|
+
// returns an empty completion ~2/3 of the time on this prompt, collapsing every fan-out to single.
|
|
204
329
|
...(cfg.routerModel ? { model: cfg.routerModel } : {}),
|
|
205
330
|
}).result();
|
|
206
331
|
return res.result ?? "";
|
|
207
332
|
};
|
|
333
|
+
// §5 quality gate: a rejected/unparseable plan retries the LLM ≤1, then collapses to single (B1-B3) —
|
|
334
|
+
// never plan-fails the task; the collapse reason is logged as a router-quality signal.
|
|
208
335
|
const { subs, collapsed, rawSample } = await routePlanWithFallback(body.objective, runRoute, {
|
|
209
336
|
...(body.planContext ? { context: body.planContext } : {}),
|
|
210
337
|
...(cfg.fanoutEnabled === false ? { fanoutEnabled: false } : {}),
|
|
@@ -215,6 +342,9 @@ export function createLeaderRunner(cfg) {
|
|
|
215
342
|
};
|
|
216
343
|
const provisionWorker = async (sub) => {
|
|
217
344
|
const sessionId = `leader-${sub.workerId}-${Date.now()}`;
|
|
345
|
+
// design/68 C4: durable suspend bits per worker task (mirrors main.ts's per-task wiring) — a gated
|
|
346
|
+
// ask/AskUserQuestion suspends the worker; ctx is seeded so the surfaced token resumes on the
|
|
347
|
+
// single-agent path (the resume body re-runs the sub-objective on this worker).
|
|
218
348
|
let durableSpec = {};
|
|
219
349
|
if (cfg.durable) {
|
|
220
350
|
const d = cfg.durable;
|
|
@@ -228,7 +358,27 @@ export function createLeaderRunner(cfg) {
|
|
|
228
358
|
cfg.logger?.warn?.("leader_putctx_failed", { workerId: sub.workerId, err: String(e) });
|
|
229
359
|
});
|
|
230
360
|
}
|
|
361
|
+
// design/74 Slice 6: opt-in resource-slice suspend. A worker that overruns its per-slice budget window
|
|
362
|
+
// SUSPENDS (resumable) instead of failing; the leader's runWorker auto-resumes until the TOTAL is spent.
|
|
363
|
+
// Reuses the durable checkpoint store (so requires `cfg.durable` for the store + durable tool-results +
|
|
364
|
+
// session — the same durable-resume prerequisites). The per-slice window OVERRIDES workerLimits.maxCostUsd
|
|
365
|
+
// (spread last); the total + cumulative spend ride on the checkpoint's resource ledger (core debits it).
|
|
231
366
|
let resourceSpec = {};
|
|
367
|
+
// Slice-6 review BLOCKER: core's resource-suspend needs the FULL durable-resume prerequisites —
|
|
368
|
+
// a checkpoint store (cfg.durable), a durable tool-result store (cfg.toolResultStore; an in-memory
|
|
369
|
+
// offload makes core REFUSE to suspend), AND a durable session store (cfg.sessionStore; without it a
|
|
370
|
+
// resumed slice dies with SessionError "Entry <leafId> not found" — the worker's progress is lost,
|
|
371
|
+
// wire.ts:52-55). Require ALL THREE before applying the per-slice window: otherwise the worker's
|
|
372
|
+
// maxCostUsd would be cut to a quarter WITHOUT the ability to suspend/resume → it fails at 1/4 its
|
|
373
|
+
// budget with no warning. When opted in (resourceCfg) but a prerequisite is missing, leave the budget
|
|
374
|
+
// intact + warn (which one).
|
|
375
|
+
// §10.5 ENFORCED mutual exclusion: when the single-agent repair loop actually OWNS a worker, that worker
|
|
376
|
+
// must NOT also resource-suspend — the repair loop owns its attempt budget, and a resource-suspend mid-loop
|
|
377
|
+
// risks `attemptCount` corruption + budget overrun (§10.5: a doc aspiration is not enough, this drops
|
|
378
|
+
// `resourceSpec` by construction so the two are NEVER on the same spec). Gated on the loop being WIRED
|
|
379
|
+
// (`REPAIR_LOOP_WIRED=true` — the canary-enable slice attached a LIVE `resolveRepair`), so flipping
|
|
380
|
+
// `LEADER_REPAIR_LOOP` now engages BOTH the single-agent repair loop AND this resource-suspend exclusion for
|
|
381
|
+
// the worker the loop owns. (`REPAIR_LOOP_WIRED` is the live/inert switch — it shipped false pre-activation.)
|
|
232
382
|
const repairLoopActive = repairLoopOn && REPAIR_LOOP_WIRED;
|
|
233
383
|
if (repairLoopActive && resourceCfg) {
|
|
234
384
|
cfg.logger?.warn?.("leader_resource_suspend_disabled_for_repair_loop", { workerId: sub.workerId, reason: "LEADER_REPAIR_LOOP active — resource-suspend mutually exclusive with the repair loop (§10.5)" });
|
|
@@ -251,6 +401,12 @@ export function createLeaderRunner(cfg) {
|
|
|
251
401
|
: "no durable session store",
|
|
252
402
|
});
|
|
253
403
|
}
|
|
404
|
+
// Keep the resume ctx warm for the WHOLE first leg (found live: task02b run1). putCtx stamps
|
|
405
|
+
// `updated_at` once at provision, but reapCtx GC's any ctx older than runStaleSec that has no pending
|
|
406
|
+
// checkpoint and no task_active claim — sub-workers hold no task_active row (that lock belongs to the
|
|
407
|
+
// HTTP submit path), so a leg longer than the reap cutoff lost its ctx and the post-suspend /decide
|
|
408
|
+
// died 409 "resume context missing". Refresh inside the run; once suspended, the pending checkpoint
|
|
409
|
+
// itself shields the ctx from the reaper, and after a terminal result the ctx ages out as designed.
|
|
254
410
|
const keepCtxWarm = (runner) => {
|
|
255
411
|
const d = cfg.durable;
|
|
256
412
|
if (!d)
|
|
@@ -267,29 +423,53 @@ export function createLeaderRunner(cfg) {
|
|
|
267
423
|
};
|
|
268
424
|
return runner;
|
|
269
425
|
};
|
|
426
|
+
// design/68 §8 F2(a) — factory-env worker + self-upload diff-out (preferred; static mode = compat below).
|
|
270
427
|
if (cfg.s3 && cfg.envFactory) {
|
|
271
428
|
const s3 = cfg.s3;
|
|
272
429
|
const envFactory = cfg.envFactory;
|
|
273
|
-
const baseSha = body.baseSha;
|
|
430
|
+
const baseSha = body.baseSha; // guarded non-empty at entry (narrowing is lost inside this closure)
|
|
274
431
|
const seedCmd = body.seedCmd;
|
|
432
|
+
// workerId is validateSubtasks-clean ([A-Za-z0-9._-]+) → safe as a key segment; the presigner
|
|
433
|
+
// backstop-rejects traversal anyway. One object per worker per leader run; a repair re-run overwrites.
|
|
275
434
|
const key = `${s3.keyPrefix ?? "leader-diff"}/${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}/${sub.workerId}.patch`;
|
|
435
|
+
// The presigned URL must outlive the worker: it self-uploads its diff at the END of its run, which
|
|
436
|
+
// can be the full leader deadline (24h). The old `Math.min(3600, …)` clamp expired mid-run for any
|
|
437
|
+
// worker > 1h → the upload 403'd and the diff (progress) was lost. Track the worker deadline + slack.
|
|
438
|
+
// (Codex: instant-signing at upload time, from the control plane, is the cleaner long-term fix.)
|
|
276
439
|
const ttl = presignTtlSec;
|
|
277
440
|
const base = { endpoint: s3.endpoint, bucket: s3.bucket, accessKey: s3.accessKey, secretKey: s3.secretKey, ...(s3.region ? { region: s3.region } : {}), key, expiresSec: ttl };
|
|
278
441
|
const putUrl = presignS3Url({ ...base, method: "PUT" });
|
|
279
442
|
const getUrl = presignS3Url({ ...base, method: "GET" });
|
|
280
443
|
const script = buildUploadScript({ repoDir: repo, baseSha, putUrl, workDir: W });
|
|
444
|
+
// Staging runs adapter-side before the agent's first workspace call: seed the base repo at the worker
|
|
445
|
+
// branch + plant the upload script (the presigned URL never passes through the model).
|
|
446
|
+
// Resume-safe (BL-1): stageWorkerEnv no-ops on a resumed snapshot (worker branch already present)
|
|
447
|
+
// instead of re-running `git checkout -b` (which would fail "branch exists" and kill the resumed
|
|
448
|
+
// worker). Now load-bearing because the prod auto-resume landed (leader.ts non-verify path, 9a91c60).
|
|
281
449
|
const stage = async (env) => {
|
|
282
450
|
await stageWorkerEnv(env, { seedCmd, repo, branch: sub.branch, uploadScriptPath: `${W}/.leader-upload.sh`, uploadScript: script });
|
|
451
|
+
// #16 tail (search 2026-06-17): INCREMENTAL progress upload. The upload script is READ-ONLY git
|
|
452
|
+
// (format-patch base..HEAD — no add/commit/index write), so a background loop re-running it keeps the
|
|
453
|
+
// worker's fixed diff key at its latest COMMITTED progress. If the env HARD-CRASHES before its final /
|
|
454
|
+
// belt upload, salvage (fetchUploadedDiff) then recovers up to the last commit instead of losing all
|
|
455
|
+
// (run 019eca71's "4 commits vaporized" was exactly a failed worker that never uploaded). No git
|
|
456
|
+
// concurrency (read-only); the teardown belt upload stays authoritative (same key, complete diff).
|
|
457
|
+
// Fire-and-forget + NEVER awaited: the loop never exits, so staging must not block on it — whether the
|
|
458
|
+
// env's exec detaches or blocks, the loop RUNS either way and the dangling promise is reaped when the
|
|
459
|
+
// pod dies. Best-effort: a launch failure (no nohup, etc.) just falls back to today's end-only upload.
|
|
283
460
|
void sh(env)(`nohup sh -c 'while true; do sleep 90; sh ${W}/.leader-upload.sh >/dev/null 2>&1 || true; done' </dev/null >/dev/null 2>&1 &`).catch(() => { });
|
|
284
461
|
};
|
|
285
462
|
return {
|
|
286
463
|
workerId: sub.workerId, sessionId, branch: sub.branch,
|
|
287
|
-
baseSha,
|
|
464
|
+
baseSha, // seedCmd reproduces the durable base — same sha for every worker
|
|
288
465
|
runner: keepCtxWarm(new Runner({
|
|
289
466
|
brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing,
|
|
290
467
|
...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}),
|
|
291
468
|
...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}),
|
|
292
469
|
executionEnvFactory: (ctx) => withStaging(envFactory(ctx), stage, async (e) => {
|
|
470
|
+
// Belt (task02b run6): workers that did the work but never `git commit`ed upload an EMPTY diff
|
|
471
|
+
// (diff-out is committed-state vs base) — auto-commit any uncommitted work first. No-op for a
|
|
472
|
+
// worker that committed properly; the commit identity marks belt-captured work for the reviewer.
|
|
293
473
|
await sh(e)(`cd ${repo} && git add -A && git -c user.name='leader-belt' -c user.email='belt@leader' commit -qm 'belt: auto-commit uncommitted worker output' || true; sh ${W}/.leader-upload.sh`);
|
|
294
474
|
}),
|
|
295
475
|
})),
|
|
@@ -313,6 +493,8 @@ export function createLeaderRunner(cfg) {
|
|
|
313
493
|
};
|
|
314
494
|
};
|
|
315
495
|
const provisionIntegrationSandbox = async () => {
|
|
496
|
+
// Factory lane (k8s or e2b): one fresh env from the service factory; lazy-connect — first exec
|
|
497
|
+
// provisions the pod/VM, destroy() reaps it. Static lane: the original explicit E2B env.
|
|
316
498
|
if (cfg.envFactory) {
|
|
317
499
|
const env = cfg.envFactory({ sessionId: `leader-integ-${Date.now()}` });
|
|
318
500
|
try {
|
|
@@ -328,6 +510,8 @@ export function createLeaderRunner(cfg) {
|
|
|
328
510
|
if (!cfg.e2bApiKey)
|
|
329
511
|
throw new Error("leader wire: no envFactory and no e2bApiKey");
|
|
330
512
|
const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs });
|
|
513
|
+
// Once connected, the VM is billable — if seeding throws, destroy it HERE before propagating, otherwise
|
|
514
|
+
// mergeBranches never receives the `destroy` closure and the sandbox leaks until E2B's timeout reaps it.
|
|
331
515
|
if (!(await env.connect()).ok) {
|
|
332
516
|
await env.destroy().catch(() => { });
|
|
333
517
|
throw new Error("integ connect failed");
|
|
@@ -343,7 +527,11 @@ export function createLeaderRunner(cfg) {
|
|
|
343
527
|
return { env: asIntegrationEnv(env), destroy: () => env.destroy().then(() => { }), ...(mkRepair(env, repo, body.oracleFiles ?? []) ? { repair: mkRepair(env, repo, body.oracleFiles ?? []) } : {}), ...(mkConflictResolver(env, repo, body.oracleFiles ?? []) ? { conflictResolver: mkConflictResolver(env, repo, body.oracleFiles ?? []) } : {}) };
|
|
344
528
|
};
|
|
345
529
|
const push = async (integratedPatch, baseSha) => {
|
|
530
|
+
// Coordinator (control plane, creds): clone durable remote, apply integrated series, force-with-lease push.
|
|
531
|
+
// 🔴 requires `git` on the service host PATH (deploy req).
|
|
346
532
|
const dir = mkdtempSync(join(tmpdir(), "leader-coord-"));
|
|
533
|
+
// Force C locale so the `raced` regex below matches git's (English) push-rejection messages regardless of
|
|
534
|
+
// the host locale — otherwise a translated message → regex miss → a real race mislabeled non-retryable (council #5).
|
|
347
535
|
const gitEnv = { ...process.env, LC_ALL: "C" };
|
|
348
536
|
try {
|
|
349
537
|
execFileSync("git", ["clone", "-q", body.durableRemote, dir], { env: gitEnv });
|
|
@@ -353,12 +541,26 @@ export function createLeaderRunner(cfg) {
|
|
|
353
541
|
execFileSync("git", ["-C", dir, "am", "--3way", ".leader.patch"], { env: gitEnv });
|
|
354
542
|
rmSync(join(dir, ".leader.patch"));
|
|
355
543
|
const ref = body.targetRef ?? "refs/heads/main";
|
|
544
|
+
// CAS against the TARGET ref's ACTUAL current tip (not baseSha). The old `=ref:baseSha` lease assumed
|
|
545
|
+
// the target ref already pointed at baseSha — but a FRESH ref (or one at any other commit) is never at
|
|
546
|
+
// baseSha, so the lease rejected EVERY such push and mislabeled it "raced" (found live: auto1 reached
|
|
547
|
+
// push after a clean 6-worker fan-out + green gradle, and failed only here). ls-remote gives the ref's
|
|
548
|
+
// current oid (empty = it doesn't exist yet) → lease against THAT, which still detects a real concurrent
|
|
549
|
+
// merge race (the ref moved since we read it) but lets a normal create/update through.
|
|
550
|
+
// Does the target ref already exist? (exact full-ref match; --refs drops peeled annotated-tag lines.)
|
|
356
551
|
const ls = execFileSync("git", ["-C", dir, "ls-remote", "--refs", "origin", ref], { encoding: "utf8", env: gitEnv });
|
|
357
552
|
const exists = ls.split("\n").some((l) => l.split("\t")[1] === ref);
|
|
358
553
|
if (exists) {
|
|
554
|
+
// Existing ref → keep the original CAS against baseSha (detects a concurrent merge that moved the ref
|
|
555
|
+
// off the base this run started from — council#2). NOT against a just-read end-of-run tip: that would
|
|
556
|
+
// let leader B force-push over leader A's concurrent merge (Codex review #1). A ref that exists but
|
|
557
|
+
// isn't at baseSha → refuse (use a fresh per-run targetRef to avoid that — the proving-ground does).
|
|
359
558
|
execFileSync("git", ["-C", dir, "push", `--force-with-lease=${ref}:${baseSha}`, "origin", `HEAD:${ref}`], { env: gitEnv });
|
|
360
559
|
}
|
|
361
560
|
else {
|
|
561
|
+
// Absent → create with a "must not exist" lease (empty expected oid): a concurrent create races safely
|
|
562
|
+
// (rejected as stale info) instead of silently fast-forwarding. The original `:baseSha` lease wrongly
|
|
563
|
+
// rejected a fresh ref (it's never at baseSha) — that was auto1's only failure after a green build.
|
|
362
564
|
execFileSync("git", ["-C", dir, "push", `--force-with-lease=${ref}:`, "origin", `HEAD:${ref}`], { env: gitEnv });
|
|
363
565
|
}
|
|
364
566
|
return { ok: true, ref };
|
|
@@ -378,14 +580,39 @@ export function createLeaderRunner(cfg) {
|
|
|
378
580
|
push,
|
|
379
581
|
testCmd: body.testCmd,
|
|
380
582
|
repoDir: repo, workerRepoDir: repo,
|
|
381
|
-
|
|
583
|
+
// Per-wave fan-out deadline. LEADER_TIMEOUT_MS raises it (raise-only, parity with TASK_TIMEOUT_SEC —
|
|
584
|
+
// found live: task02b run5, porting workers + collapse-solo all 'run aborted' at the 600s default while
|
|
585
|
+
// mid-gradle; the per-worker presign ttl below tracks the same knob).
|
|
586
|
+
timeoutMs: leaderTimeoutMs, maxConcurrency: 4, // Semaphore cap; the planner emits ≤6 sub-tasks
|
|
587
|
+
// replan-lite (design/68 §6) always on in the wired leader; LEADER_BUDGET_USD bounds the fan-out spend.
|
|
382
588
|
replan: { ...(process.env.LEADER_BUDGET_USD ? { budgetUsd: Number(process.env.LEADER_BUDGET_USD) } : {}) },
|
|
589
|
+
// LEADER-REPAIRLOOP-INTEGRATION §10.3 — the merge push-hold-on-signal (OFF unless LEADER_MEASURE_GATES). It
|
|
590
|
+
// needs NO extra sandbox: `strongOracleSeeded` keys on whether a hidden held-out oracle was injected into the
|
|
591
|
+
// integration sandbox (`injectOracles` runs `body.oracleFiles`), and the §10.3 hold combines it with the
|
|
592
|
+
// existing observe-only `measureCmd` result inside `mergeBranches`. §10.4's out-of-process measure grader
|
|
593
|
+
// (`measureDrivesRepair`) is a separate re-seedable sandbox — the canary-enable add-on (§6 step 5); it is
|
|
594
|
+
// intentionally NOT wired here in v1 (a half-mint would be a stopgap), so `measureGates` ships the §10.3
|
|
595
|
+
// signal-hold only. With LEADER_MEASURE_GATES off this whole block is absent → byte-identical merge path.
|
|
383
596
|
...(measureGatesOn
|
|
384
597
|
? { mergeGates: { measureGates: true, ...((body.oracleFiles?.length ?? 0) > 0 ? { strongOracleSeeded: true } : {}) } }
|
|
385
598
|
: {}),
|
|
386
599
|
...(cfg.logger ? { logger: cfg.logger } : {}),
|
|
387
600
|
};
|
|
601
|
+
// §10.8 — the SINGLE wire-call helper for the opt-in single-agent repair loop (LEADER_REPAIR_LOOP). The
|
|
602
|
+
// canary-enable slice attaches a LIVE async `resolve(solo, sub)` that, per solo worker, provisions a DEDICATED
|
|
603
|
+
// oracle-seeded GRADER sandbox (a SEPARATE sandbox from the worker + the integration sandbox — distinct object/
|
|
604
|
+
// sandboxId by construction, §10.2 structural isolation) and binds the per-worker diff source + the concrete
|
|
605
|
+
// Runner. OFF-by-default: `resolve` is attached ONLY when `repairLoopOn` (LEADER_REPAIR_LOOP=true); with the
|
|
606
|
+
// flag off `resolve` is undefined → `attachRepairLoopDeps` is a NO-OP → `deps.repairLoop` stays unset → the
|
|
607
|
+
// single-agent default path is byte-identical to today. The §10.6 push chokepoint (merge.ts) is LIVE
|
|
608
|
+
// regardless: once any report carries a `repairTerminal`, it holds.
|
|
609
|
+
//
|
|
610
|
+
// The grader is provisioned the SAME way as the integration sandbox (provisionIntegrationSandbox: raw env →
|
|
611
|
+
// seed → injectOracles → integBase), then exposed as a `GraderHandle` (the raw RemoteExecutionEnv IS an
|
|
612
|
+
// ExecutionEnv). `graderDestroy` reaps it in `runRepairLoopForLeader`'s `finally`. On a seed/inject throw the
|
|
613
|
+
// env is destroyed before propagating (mirrors provisionIntegrationSandbox :587-590 / :604-606).
|
|
388
614
|
const resolveRepair = async (solo, _sub) => {
|
|
615
|
+
// Provision a DEDICATED grader: factory lane mints a fresh env (lazy-connect); static lane connects an E2B VM.
|
|
389
616
|
let env;
|
|
390
617
|
if (cfg.envFactory) {
|
|
391
618
|
env = cfg.envFactory({ sessionId: `leader-grader-${Date.now()}` });
|
|
@@ -400,6 +627,8 @@ export function createLeaderRunner(cfg) {
|
|
|
400
627
|
}
|
|
401
628
|
env = e2b;
|
|
402
629
|
}
|
|
630
|
+
// Seed the base repo + inject the hidden oracle ONLY in this grader (never the worker env). On a throw,
|
|
631
|
+
// destroy the billable env before propagating (else it leaks until the adapter's timeout reaps it).
|
|
403
632
|
let integBase;
|
|
404
633
|
try {
|
|
405
634
|
await sh(env)(body.seedCmd);
|
|
@@ -417,20 +646,33 @@ export function createLeaderRunner(cfg) {
|
|
|
417
646
|
repoDir: repo,
|
|
418
647
|
integBase,
|
|
419
648
|
};
|
|
649
|
+
// The worker diff source: factory lane = the worker's self-upload (`solo.fetchDiff`); static lane = pull the
|
|
650
|
+
// committed `base..HEAD` series straight out of the worker's still-alive env (the same merge `pullDiff` path).
|
|
420
651
|
const workerRepoDir = repo;
|
|
421
652
|
const pullWorkerDiff = solo.fetchDiff
|
|
422
|
-
?
|
|
653
|
+
? // 🔴 BL-33 factory-lane residual: the self-upload path captures only what the fix turn UPLOADED; core's
|
|
654
|
+
// repairObjective carries no upload mandate, so an un-uploaded fix is missed. A deterministic belt needs
|
|
655
|
+
// a worker-env exec handle the factory lane does not surface (env-recording factory = follow-up). The
|
|
656
|
+
// fork2.1 stale-diff guard keeps this SAFE (no false candidate) until then.
|
|
423
657
|
solo.fetchDiff
|
|
424
658
|
: async () => {
|
|
659
|
+
// 🔴 BL-33 — the STATIC lane EXPOSES the worker env (`solo.diffEnv`), so deterministically belt-commit
|
|
660
|
+
// the worker's UNCOMMITTED fix-turn work BEFORE the committed-only `format-patch base..HEAD` pull —
|
|
661
|
+
// else attempts ≥2 grade a STALE diff (the fix never observed). Best-effort + only when there is a
|
|
662
|
+
// change to commit (no empty commits polluting the series). Mirrors the teardown belt, run per-grade.
|
|
425
663
|
const wenv = solo.diffEnv;
|
|
426
664
|
await wenv
|
|
427
665
|
.exec(`bash -lc ${JSON.stringify(`cd ${repo} && git add -A && (git diff --cached --quiet || git -c user.email=w@w.co -c user.name=worker commit -q -m repair-wip)`)}`)
|
|
428
666
|
.catch(() => { });
|
|
429
667
|
return pullDiff(solo.diffEnv, solo.baseSha, { ref: solo.branch, ...(workerRepoDir ? { cwd: workerRepoDir } : {}) });
|
|
430
668
|
};
|
|
669
|
+
// The trusted, spec-derived oracle steps (the integration testCmd) run in the grader; NEVER worker-authored.
|
|
431
670
|
const oracleSteps = [{ command: body.testCmd, cwd: repo, label: "oracle-test" }];
|
|
671
|
+
// tier: a seeded hidden held-out oracle clears to `trusted_hidden`; a compile-only gate is `property_harness_weak`.
|
|
432
672
|
const oracleFiles = body.oracleFiles ?? [];
|
|
433
673
|
const passTier = oracleFiles.length > 0 ? "trusted_hidden" : "property_harness_weak";
|
|
674
|
+
// fork1.1 — make the INTENTIONAL factory-lane identity-check skip observable (distinct from an
|
|
675
|
+
// accidental workerEnv omission, which onWarn's generic MINOR-2 warning can't tell apart).
|
|
434
676
|
if (solo.fetchDiff)
|
|
435
677
|
cfg.logger?.info?.("repair_loop_factory_lane_isolation", { workerId: solo.workerId, reason: "identity check intentionally skipped — isolation by independent grader sandbox construction (§10.2)" });
|
|
436
678
|
return {
|
|
@@ -440,9 +682,14 @@ export function createLeaderRunner(cfg) {
|
|
|
440
682
|
pullWorkerDiff,
|
|
441
683
|
oracleSteps,
|
|
442
684
|
passTier,
|
|
685
|
+
// council 2026-06-17 — re-inject the seeded oracle after each hermetic reset (clean -fdx wipes it);
|
|
686
|
+
// fork1.2 — the paths a candidate patch must not touch (the oracle files' own paths).
|
|
443
687
|
...(oracleFiles.length > 0 ? { oracleFiles, oraclePaths: oracleFiles.map((f) => f.path) } : {}),
|
|
444
688
|
maxAttempts: repairLoopAttempts,
|
|
445
689
|
flakyK: oracleFlakyK,
|
|
690
|
+
// §10.2 — on the factory lane the worker's RAW env is not surfaced (only fetchDiff), so OMIT workerEnv
|
|
691
|
+
// (runRepairLoop skips the identity check; the grader is a separate sandbox by construction). On the static
|
|
692
|
+
// lane the leader owns the worker's RemoteExecutionEnv (`solo.diffEnv` is that env) → pass it so the check runs.
|
|
446
693
|
...(!solo.fetchDiff && solo.diffEnv ? { workerEnv: solo.diffEnv } : {}),
|
|
447
694
|
log: (event, x) => event.includes("fail") || event.includes("warn") || event.includes("threw")
|
|
448
695
|
? cfg.logger?.warn?.(event, x)
|
package/dist/lsp/e2b-bridge.d.ts
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridges WS ⇄ a language server's stdio. Server command from `LSP_CMD`, port `LSP_PORT`, and a per-session
|
|
3
|
+
* **auth token** `LSP_TOKEN` (the endpoint is a public `wss://<port>-<id>.e2b.app` URL — the runner connects with
|
|
4
|
+
* `?token=<secret>`; without it, anyone with the URL could read the workspace via LSP, council #4). Frame parsing
|
|
5
|
+
* uses the unit-tested {@link FRAME_DECODER_JS} (council #1/#2/#5).
|
|
6
|
+
*/
|
|
1
7
|
export declare const BRIDGE_SOURCE: string;
|
|
8
|
+
/** Language server command per languageId. P1 = typescript/javascript; dart/kotlin land with their template servers.
|
|
9
|
+
* `--stdio` only where the server needs it to pick stdio over its other transports (the node-based servers);
|
|
10
|
+
* gopls/jdtls/kotlin-language-server/sourcekit-lsp/`dart language-server` speak LSP over stdio by default. */
|
|
2
11
|
export declare const SERVER_CMD: Readonly<Record<string, string>>;
|
|
12
|
+
/** npm packages a non-baked sandbox needs (on-the-fly install). Languages absent here (go) REQUIRE a baked template. */
|
|
3
13
|
export declare const SERVER_NPM: Readonly<Record<string, string>>;
|
|
14
|
+
/** Bridge dir + port inside the sandbox. One bridge process per language → distinct ports. */
|
|
4
15
|
export declare const BRIDGE_DIR = "/home/user/.lsp-bridge";
|
|
5
16
|
export declare function portForLanguage(language: string): number;
|
|
17
|
+
/** FOREGROUND install (run via `env.exec` — must finish before the start). A baked template makes both checks
|
|
18
|
+
* skip instantly; a non-baked sandbox npm-installs the server + ws here (slow once per sandbox). */
|
|
6
19
|
export declare function lspInstallCommand(language: string): string;
|
|
20
|
+
/** Start the bridge — run as a TRUE background command (`env.startBackground`), NOT `&`-backgrounded inside a
|
|
21
|
+
* foreground run: E2B reaps the foreground process group on completion, killing an in-shell `&`/nohup child.
|
|
22
|
+
* So node is the FOREGROUND here and E2B keeps the background command alive. */
|
|
7
23
|
export declare function lspStartCommand(language: string, port: number, token: string): string;
|
|
8
24
|
//# sourceMappingURL=e2b-bridge.d.ts.map
|