humanish 0.106.1 → 0.107.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/AGENTS.md +4 -4
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -8
- package/README.md +8 -3
- package/dist/actors/codex/app-server-client.js +2 -1
- package/dist/actors/codex/app-server-trace.d.ts +0 -1
- package/dist/actors/codex/app-server-trace.js +1 -3
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/protocol-compat.d.ts +27 -0
- package/dist/actors/codex/protocol-compat.js +357 -0
- package/dist/actors/codex/protocol-contract.d.ts +61 -0
- package/dist/actors/codex/protocol-contract.js +471 -0
- package/dist/actors/codex/qualified-versions.d.ts +30 -3
- package/dist/actors/codex/qualified-versions.js +50 -5
- package/dist/actors/codex/restricted-executable.d.ts +24 -0
- package/dist/actors/codex/restricted-executable.js +97 -22
- package/dist/actors/codex/restricted-launch.d.ts +7 -1
- package/dist/actors/codex/restricted-launch.js +42 -3
- package/dist/actors/codex/restricted-notifications.d.ts +101 -0
- package/dist/actors/codex/restricted-notifications.js +277 -0
- package/dist/actors/codex/restricted-participant.d.ts +30 -0
- package/dist/actors/codex/restricted-participant.js +60 -2
- package/dist/actors/codex/restricted-policy.d.ts +9 -1
- package/dist/actors/codex/restricted-session.d.ts +14 -1
- package/dist/actors/codex/restricted-session.js +50 -17
- package/dist/actors/codex/restricted-transport.d.ts +29 -0
- package/dist/actors/codex/restricted-transport.js +139 -27
- package/dist/actors/codex/restricted-turn.d.ts +19 -4
- package/dist/actors/codex/restricted-turn.js +43 -30
- package/dist/actors/computer-use/actor.d.ts +1 -1
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/loop/backstop.js +1 -1
- package/dist/actors/computer-use/loop/ending.d.ts +2 -2
- package/dist/actors/computer-use/loop/ending.js +2 -2
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +3 -3
- package/dist/actors/computer-use/loop/trace.js +2 -2
- package/dist/actors/computer-use/loop/types.d.ts +14 -5
- package/dist/actors/computer-use/loop.js +4 -4
- package/dist/actors/computer-use/openai-provider.d.ts +1 -1
- package/dist/actors/computer-use/openai-provider.js +2 -2
- package/dist/actors/contract.d.ts +9 -7
- package/dist/actors/local-agent/cli.js +1 -1
- package/dist/actors/scripted-browser/actor.d.ts +2 -2
- package/dist/actors/scripted-browser/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +18 -0
- package/dist/actors/scripted-browser/types.d.ts +11 -1
- package/dist/actors/stop-conditions.js +1 -3
- package/dist/analysis/automatic-completion.d.ts +13 -8
- package/dist/analysis/automatic-completion.js +14 -8
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/analysis/automatic-config.js +2 -2
- package/dist/analysis/automatic.d.ts +10 -4
- package/dist/analysis/automatic.js +17 -13
- package/dist/analysis/diagnostics.d.ts +23 -0
- package/dist/analysis/diagnostics.js +112 -0
- package/dist/analysis/evidence-sources.js +2 -2
- package/dist/analysis/evidence.js +6 -6
- package/dist/analysis/execute.d.ts +7 -1
- package/dist/analysis/execute.js +39 -12
- package/dist/analysis/job.d.ts +8 -5
- package/dist/analysis/job.js +15 -14
- package/dist/analysis/load.d.ts +1 -1
- package/dist/analysis/load.js +5 -5
- package/dist/analysis/provider.d.ts +9 -1
- package/dist/analysis/restricted-codex.d.ts +2 -0
- package/dist/analysis/restricted-codex.js +10 -1
- package/dist/analysis/service.d.ts +2 -0
- package/dist/analysis/service.js +31 -12
- package/dist/analysis/sharing.d.ts +2 -2
- package/dist/analysis/sharing.js +5 -5
- package/dist/analysis/store-executions.d.ts +5 -5
- package/dist/analysis/store-executions.js +12 -12
- package/dist/analysis/store.d.ts +4 -4
- package/dist/analysis/store.js +13 -13
- package/dist/cli/commands/analysis-signals.d.ts +2 -1
- package/dist/cli/commands/analysis-signals.js +4 -1
- package/dist/cli/commands/analyze.js +4 -2
- package/dist/cli/commands/comms.js +8 -1
- package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +26 -14
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +3 -4
- package/dist/cli/commands/lab-route-run.d.ts +6 -4
- package/dist/cli/commands/lab-route-run.js +6 -2
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
- package/dist/cli/commands/lab-route-scripted.js +0 -1
- package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
- package/dist/cli/commands/lab-route-shared-world.js +0 -1
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
- package/dist/cli/commands/lab-route-terminal.js +0 -1
- package/dist/cli/commands/lab-run.js +76 -45
- package/dist/cli/commands/lab-scorer.d.ts +0 -2
- package/dist/cli/commands/lab.js +12 -6
- package/dist/cli/commands/observe.js +22 -0
- package/dist/cli/commands/run-signals.d.ts +30 -0
- package/dist/cli/commands/run-signals.js +146 -0
- package/dist/cli/commands/runs.js +10 -8
- package/dist/cli/commands/watch.js +12 -10
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.js +10 -2
- package/dist/cli/io.d.ts +5 -4
- package/dist/cli/io.js +12 -8
- package/dist/cli/program.js +3 -3
- package/dist/cli/renamed-options.d.ts +11 -0
- package/dist/cli/renamed-options.js +18 -0
- package/dist/cli/telemetry.d.ts +2 -2
- package/dist/cli/telemetry.js +1 -1
- package/dist/comms/capture-surface.d.ts +1 -1
- package/dist/comms/catch-host.d.ts +1 -1
- package/dist/comms/connections.js +4 -4
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- package/dist/comms/lease-store.js +7 -7
- package/dist/comms/types.js +1 -1
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- package/dist/evidence/redaction.js +1 -1
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +7 -9
- package/dist/feedback/export-bundle.js +4 -4
- package/dist/feedback/export.js +9 -9
- package/dist/feedback/feedback.d.ts +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +3 -6
- package/dist/keys/key-resolution.d.ts +3 -1
- package/dist/keys/key-resolution.js +18 -16
- package/dist/lab/adapter-extension.d.ts +28 -6
- package/dist/lab/adapter-extension.js +65 -126
- package/dist/lab/adapter-scorer-loader.d.ts +25 -5
- package/dist/lab/adapter-scorer-loader.js +24 -0
- package/dist/lab/composition-rules.js +20 -20
- package/dist/lab/config.js +28 -26
- package/dist/lab/device-presets.d.ts +2 -2
- package/dist/lab/discover.js +1 -3
- package/dist/lab/doctor.d.ts +44 -9
- package/dist/lab/doctor.js +149 -41
- package/dist/lab/init-plan.js +1 -3
- package/dist/lab/keys.js +1 -1
- package/dist/lab/lab-deps.d.ts +85 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +8 -7
- package/dist/lab/parse/comms.js +3 -2
- package/dist/lab/parse/execution.js +3 -2
- package/dist/lab/parse/subject-state.js +2 -1
- package/dist/lab/parse/subject.js +2 -1
- package/dist/lab/parse/values.d.ts +0 -1
- package/dist/lab/parse/values.js +0 -3
- package/dist/lab/persona-resolve.d.ts +3 -3
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +0 -2
- package/dist/lab/plan-base.js +6 -4
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +22 -4
- package/dist/lab/plan.d.ts +3 -11
- package/dist/lab/plan.js +18 -42
- package/dist/lab/preflight-result.js +0 -2
- package/dist/lab/preflight.d.ts +0 -3
- package/dist/lab/preflight.js +1 -1
- package/dist/lab/requirements.d.ts +20 -0
- package/dist/lab/requirements.js +54 -0
- package/dist/lab/route-inputs.d.ts +23 -12
- package/dist/lab/route-inputs.js +48 -51
- package/dist/lab/routing.d.ts +19 -24
- package/dist/lab/routing.js +14 -47
- package/dist/lab/run-lab-events.d.ts +6 -11
- package/dist/lab/run-lab-events.js +3 -11
- package/dist/lab/run-lab-homes.d.ts +64 -0
- package/dist/lab/run-lab-homes.js +3 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +45 -275
- package/dist/lab/summary.d.ts +9 -4
- package/dist/lab/summary.js +15 -8
- package/dist/lab/types.d.ts +132 -132
- package/dist/lab/validation.d.ts +15 -15
- package/dist/lab/validation.js +28 -28
- package/dist/lab/warnings.js +20 -19
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +3 -3
- package/dist/observer/data.js +2 -2
- package/dist/observer/render.js +2 -2
- package/dist/observer/run-routes.d.ts +1 -1
- package/dist/observer/run-routes.js +5 -5
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +34 -3
- package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
- package/dist/routes/computer-use/bundle-parts.js +10 -3
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +9 -15
- package/dist/routes/computer-use/diagnostics.d.ts +1 -1
- package/dist/routes/computer-use/diagnostics.js +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
- package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
- package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +19 -43
- package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
- package/dist/routes/computer-use/fanout-bundle.js +25 -29
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
- package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
- package/dist/routes/computer-use/in-process-desktop.js +3 -9
- package/dist/routes/computer-use/live-flush.d.ts +7 -5
- package/dist/routes/computer-use/live-flush.js +19 -27
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +12 -11
- package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
- package/dist/routes/computer-use/local-tree-pack.js +4 -5
- package/dist/routes/computer-use/local-vm.d.ts +11 -8
- package/dist/routes/computer-use/local-vm.js +39 -66
- package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
- package/dist/routes/computer-use/participant-desktop.js +5 -25
- package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
- package/dist/routes/computer-use/participant-facts.d.ts +7 -1
- package/dist/routes/computer-use/participant-facts.js +12 -1
- package/dist/routes/computer-use/participant-model.d.ts +19 -11
- package/dist/routes/computer-use/participant-model.js +49 -25
- package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
- package/dist/routes/computer-use/participant-prompt.js +4 -4
- package/dist/routes/computer-use/participant-runs.d.ts +6 -6
- package/dist/routes/computer-use/participant-runs.js +8 -8
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +52 -60
- package/dist/routes/computer-use/preflight.d.ts +3 -5
- package/dist/routes/computer-use/preflight.js +20 -16
- package/dist/routes/computer-use/rerun-selection.js +10 -6
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +40 -30
- package/dist/routes/computer-use/route.d.ts +3 -4
- package/dist/routes/computer-use/route.js +21 -19
- package/dist/routes/computer-use/self-report.d.ts +2 -2
- package/dist/routes/computer-use/self-report.js +4 -4
- package/dist/routes/computer-use/setup.d.ts +8 -14
- package/dist/routes/computer-use/setup.js +96 -72
- package/dist/routes/computer-use/single-bundle.d.ts +8 -11
- package/dist/routes/computer-use/single-bundle.js +20 -25
- package/dist/routes/computer-use/subject-projection.d.ts +5 -7
- package/dist/routes/computer-use/subject-projection.js +20 -19
- package/dist/routes/computer-use/types.d.ts +169 -210
- package/dist/routes/computer-use/types.js +13 -5
- package/dist/routes/preview.js +0 -1
- package/dist/routes/scripted/bundle.d.ts +3 -6
- package/dist/routes/scripted/bundle.js +11 -16
- package/dist/routes/scripted/plan.d.ts +5 -7
- package/dist/routes/scripted/plan.js +6 -4
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +10 -6
- package/dist/routes/scripted/route.js +10 -11
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +1 -1
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +22 -21
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +9 -5
- package/dist/routes/scripted/surface-records.js +1 -1
- package/dist/routes/scripted/surface-sessions.d.ts +2 -2
- package/dist/routes/scripted/surface-sessions.js +4 -4
- package/dist/routes/scripted/types.d.ts +19 -36
- package/dist/routes/scripted/types.js +1 -2
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
- package/dist/routes/shared-world/bundle.d.ts +2 -2
- package/dist/routes/shared-world/bundle.js +22 -26
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +4 -4
- package/dist/routes/shared-world/comms.d.ts +5 -4
- package/dist/routes/shared-world/comms.js +28 -41
- package/dist/routes/shared-world/external-public.d.ts +5 -5
- package/dist/routes/shared-world/external-public.js +19 -20
- package/dist/routes/shared-world/handoff.d.ts +4 -4
- package/dist/routes/shared-world/handoff.js +50 -50
- package/dist/routes/shared-world/lobby-code.d.ts +5 -5
- package/dist/routes/shared-world/lobby-code.js +13 -13
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +43 -48
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +1 -2
- package/dist/routes/shared-world/provenance.d.ts +4 -4
- package/dist/routes/shared-world/provenance.js +4 -4
- package/dist/routes/shared-world/provisioned.d.ts +3 -2
- package/dist/routes/shared-world/provisioned.js +46 -40
- package/dist/routes/shared-world/result.js +31 -19
- package/dist/routes/shared-world/route.js +37 -41
- package/dist/routes/shared-world/setup.d.ts +5 -4
- package/dist/routes/shared-world/setup.js +12 -14
- package/dist/routes/shared-world/types.d.ts +53 -126
- package/dist/routes/shared-world/types.js +2 -2
- package/dist/routes/terminal/adapter.d.ts +8 -8
- package/dist/routes/terminal/adapter.js +28 -125
- package/dist/routes/terminal/bundle.d.ts +7 -12
- package/dist/routes/terminal/bundle.js +24 -34
- package/dist/routes/terminal/credentials.d.ts +2 -2
- package/dist/routes/terminal/credentials.js +16 -16
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +9 -11
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +6 -6
- package/dist/routes/terminal/ledger.js +9 -9
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +21 -20
- package/dist/routes/terminal/live-sandbox.d.ts +3 -2
- package/dist/routes/terminal/live-sandbox.js +20 -20
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +13 -9
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +4 -4
- package/dist/routes/terminal/route.js +26 -26
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +3 -3
- package/dist/routes/terminal/sandbox.js +9 -9
- package/dist/routes/terminal/session.js +16 -14
- package/dist/routes/terminal/token-usage.js +5 -5
- package/dist/routes/terminal/trace.d.ts +5 -8
- package/dist/routes/terminal/trace.js +9 -64
- package/dist/routes/terminal/types.d.ts +85 -93
- package/dist/routes/terminal/types.js +9 -4
- package/dist/run/active-runs.d.ts +13 -0
- package/dist/run/active-runs.js +12 -0
- package/dist/run/bundle-shape.d.ts +2 -1
- package/dist/run/bundle-shape.js +4 -4
- package/dist/run/bundle.d.ts +63 -56
- package/dist/run/bundle.js +9 -8
- package/dist/run/cost-summary.js +3 -2
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +10 -10
- package/dist/run/detail.d.ts +5 -5
- package/dist/run/detail.js +6 -6
- package/dist/run/dry-run.js +5 -12
- package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
- package/dist/run/{study-files.js → evidence-files.js} +5 -5
- package/dist/run/feedback-shape.js +1 -1
- package/dist/run/judge.d.ts +16 -4
- package/dist/run/judge.js +24 -7
- package/dist/run/locate.d.ts +2 -0
- package/dist/run/locate.js +3 -1
- package/dist/run/outcomes.d.ts +3 -3
- package/dist/run/outcomes.js +3 -3
- package/dist/run/participant-records.d.ts +2 -2
- package/dist/run/participant-records.js +2 -2
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +19 -9
- package/dist/run/pricing.js +30 -18
- package/dist/run/projection.d.ts +13 -13
- package/dist/run/projection.js +8 -8
- package/dist/run/reclaim.d.ts +6 -0
- package/dist/run/reclaim.js +13 -3
- package/dist/run/results.d.ts +1 -1
- package/dist/run/run-index.d.ts +1 -1
- package/dist/run/run-index.js +11 -11
- package/dist/run/run.d.ts +4 -2
- package/dist/run/run.js +9 -5
- package/dist/run/sandbox-receipts.d.ts +4 -4
- package/dist/run/sandbox-receipts.js +4 -4
- package/dist/run/shared-world-evidence.d.ts +47 -47
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +11 -11
- package/dist/run/stats.d.ts +5 -5
- package/dist/run/stats.js +8 -8
- package/dist/run/status.d.ts +16 -6
- package/dist/run/status.js +31 -8
- package/dist/run/streams.d.ts +26 -19
- package/dist/run/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/transient-comms-secrets.d.ts +5 -0
- package/dist/run/transient-comms-secrets.js +12 -0
- package/dist/run-lab.d.ts +36 -34
- package/dist/run-lab.js +41 -37
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +1 -1
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +2 -2
- package/dist/subject/local-tree.js +1 -1
- package/dist/subject/node-bootstrap.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +4 -4
- package/dist/subject/runtime.js +5 -5
- package/dist/subject/serve.js +1 -1
- package/dist/subject/steps.d.ts +4 -4
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
- package/dist/substrates/e2b/cdp-probe.js +1 -1
- package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
- package/dist/substrates/e2b/desktop-browser.js +4 -4
- package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
- package/dist/substrates/e2b/desktop-cdp.js +4 -4
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +3 -3
- package/dist/substrates/e2b/desktop-media.js +2 -2
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.js +2 -2
- package/dist/substrates/local/runtime-host.d.ts +2 -0
- package/dist/substrates/local/runtime-host.js +6 -0
- package/dist/tui/actions.d.ts +7 -5
- package/dist/tui/actions.js +18 -9
- package/dist/tui-app.js +42 -42
- package/dist/verify/actor.d.ts +10 -10
- package/dist/verify/actor.js +15 -15
- package/dist/verify/artifacts.d.ts +1 -1
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/costs.d.ts +2 -2
- package/dist/verify/costs.js +2 -2
- package/dist/verify/liveness.d.ts +1 -1
- package/dist/verify/liveness.js +4 -1
- package/dist/verify/rerun.d.ts +1 -1
- package/dist/verify/rerun.js +1 -1
- package/dist/verify/shared-world.js +2 -2
- package/dist/verify/verify.js +6 -6
- package/docs/README.md +1 -1
- package/docs/architecture/actor-contract.md +60 -22
- package/docs/architecture/desktop-sessions.md +9 -9
- package/docs/architecture/external-public-shared-world.md +5 -0
- package/docs/architecture/observer.md +4 -4
- package/docs/architecture/restricted-codex-analysis.md +36 -2
- package/docs/architecture/state-driven-executor.md +4 -5
- package/docs/architecture/task-protocol-support.md +3 -5
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
- package/docs/contracts/run-bundle.md +10 -8
- package/docs/contracts/schemas.md +109 -53
- package/docs/contracts/study-analysis.md +24 -0
- package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- package/docs/product/automatic-analysis.md +1 -0
- package/docs/ramp/README.md +2 -1
- package/package.json +4 -4
- package/skills/humanish/SKILL.md +3 -2
- package/skills/humanish/agents/openai.yaml +1 -1
- package/dist/deprecated.d.ts +0 -90
- package/dist/deprecated.js +0 -106
- package/dist/lab/bag-overrides.d.ts +0 -18
- package/dist/lab/bag-overrides.js +0 -121
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
package/dist/lab/validation.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { LabConfig } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Cross-validate the computer-use fan-out declaration (per-lane
|
|
4
|
-
* message, or null when valid. Enforced at parse
|
|
5
|
-
* is itself exported npm surface). Structural
|
|
3
|
+
* Cross-validate the computer-use fan-out declaration (`per-lane-worlds`). Returns the failure
|
|
4
|
+
* message, or null when valid. Enforced at parse and re-enforced in the engine (runCuaActorLab
|
|
5
|
+
* is itself exported npm surface). Structural roster shape (id/device validity, id uniqueness) is
|
|
6
6
|
* already checked in parseLanes; this is the route-scoped XOR/cap/policy layer.
|
|
7
7
|
*/
|
|
8
8
|
export declare function cuaLaneValidationReason(config: LabConfig): string | null;
|
|
@@ -43,24 +43,24 @@ export declare function scenarioCapsValidationReason(config: LabConfig): string
|
|
|
43
43
|
/** Refuse a claimed output bound when the route cannot pass it to the first-party provider. */
|
|
44
44
|
export declare function outputTokenLimitValidationReason(config: LabConfig): string | null;
|
|
45
45
|
/**
|
|
46
|
-
* Cross-validate a
|
|
47
|
-
* or null when valid. Includes the base shared-world checks
|
|
48
|
-
* subject attestation
|
|
49
|
-
* all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (
|
|
50
|
-
* orphan actor sandboxes). Enforced at parse
|
|
46
|
+
* Cross-validate a concurrent shared-world declaration (#164 phase 2). Returns the failure message,
|
|
47
|
+
* or null when valid. Includes the base shared-world checks plus the concurrent extras: a synthetic
|
|
48
|
+
* subject attestation, a 0.0.0.0 serve bind (getHost only routes to a port bound on
|
|
49
|
+
* all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (either would
|
|
50
|
+
* orphan actor sandboxes). Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld
|
|
51
51
|
* is exported npm surface).
|
|
52
52
|
*/
|
|
53
53
|
export declare function concurrentSharedWorldValidationReason(config: LabConfig): string | null;
|
|
54
54
|
/**
|
|
55
|
-
* Cross-validate the
|
|
56
|
-
* deployment used
|
|
57
|
-
* The
|
|
58
|
-
* it
|
|
59
|
-
* are inert with no sandbox
|
|
55
|
+
* Cross-validate the external-public shared-world declaration (#164 phase 2): a real public
|
|
56
|
+
* deployment used directly as the shared plane (no getHost, no clone, no subject sandbox, no seed).
|
|
57
|
+
* The counterpart of concurrentSharedWorldValidationReason for a plane the harness does not own:
|
|
58
|
+
* it rejects every provisioned-subject field (serve/state.seed/state.checkpoint/exposure/clone/repos
|
|
59
|
+
* are inert with no sandbox, so they fail closed per invariant 6), and requires a
|
|
60
60
|
* non-loopback appUrl + allowPublicTargets + the operator-ownership attestation subject.publicTarget +
|
|
61
|
-
* concurrency >= 2 + an actors[0].lanes roster of ≥2 with
|
|
61
|
+
* concurrency >= 2 + an actors[0].lanes roster of ≥2 with exactly one host participant. The getHost synthetic
|
|
62
62
|
* gate is deliberately unreachable here (there is no internet-reachable harness-owned URL to attest).
|
|
63
|
-
* Enforced at parse
|
|
63
|
+
* Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld is exported npm surface).
|
|
64
64
|
*/
|
|
65
65
|
export declare function externalPublicSharedWorldValidationReason(config: LabConfig): string | null;
|
|
66
66
|
/** Analysis requires a live recording producer, including supported dry-run previews. */
|
package/dist/lab/validation.js
CHANGED
|
@@ -4,9 +4,9 @@ import { isHttpUrl, isLoopbackUrl } from "./parse/subject.js";
|
|
|
4
4
|
import { declaredTargets } from "./plan-participants.js";
|
|
5
5
|
import { actorResolvesToComputerUse, cuaLaneCount, MAX_CUA_LANES, registeredComputerUseActors, resolveSeatUrl, isComputerUseComposition, isScriptedBrowserComposition, isSharedWorldComposition, isTerminalProductComposition, } from "./routing.js";
|
|
6
6
|
/**
|
|
7
|
-
* Cross-validate the computer-use fan-out declaration (per-lane
|
|
8
|
-
* message, or null when valid. Enforced at parse
|
|
9
|
-
* is itself exported npm surface). Structural
|
|
7
|
+
* Cross-validate the computer-use fan-out declaration (`per-lane-worlds`). Returns the failure
|
|
8
|
+
* message, or null when valid. Enforced at parse and re-enforced in the engine (runCuaActorLab
|
|
9
|
+
* is itself exported npm surface). Structural roster shape (id/device validity, id uniqueness) is
|
|
10
10
|
* already checked in parseLanes; this is the route-scoped XOR/cap/policy layer.
|
|
11
11
|
*/
|
|
12
12
|
export function cuaLaneValidationReason(config) {
|
|
@@ -16,8 +16,8 @@ export function cuaLaneValidationReason(config) {
|
|
|
16
16
|
if (structuralReason) {
|
|
17
17
|
return structuralReason;
|
|
18
18
|
}
|
|
19
|
-
// clone.fanout is a
|
|
20
|
-
// Fan-out is declared via actors[0].count
|
|
19
|
+
// clone.fanout is a declared behavior change: rejected on the cua route (was inert-warned).
|
|
20
|
+
// Fan-out is declared via `actors[0].count` or `actors[0].lanes`; subject.clone.fanout never applied here.
|
|
21
21
|
if (config.subject.clone?.fanout !== undefined) {
|
|
22
22
|
return "`subject.clone.fanout` is not used on the computer-use route: declare fan-out with actors[0].count (homogeneous) or actors[0].lanes (a roster of participants). (No current route reads clone.fanout.)";
|
|
23
23
|
}
|
|
@@ -49,11 +49,11 @@ export function cuaLaneValidationReason(config) {
|
|
|
49
49
|
if (participantCount > MAX_CUA_LANES) {
|
|
50
50
|
return `Computer-use fan-out is capped at ${MAX_CUA_LANES} participants (declared ${participantCount}); N concurrent paid desktops is real spend, and there is no override above the cap this slice.`;
|
|
51
51
|
}
|
|
52
|
-
// Public targets fan out into N independent worlds driving the
|
|
53
|
-
// ambiguous shared-world-ish shape, not a per-
|
|
54
|
-
// every roster
|
|
55
|
-
// `subject.topology: shared-world` is
|
|
56
|
-
//
|
|
52
|
+
// Public targets fan out into N independent worlds driving the same public app, which is an
|
|
53
|
+
// ambiguous shared-world-ish shape, not a per-participant target swarm. Permit N>1 public runs only
|
|
54
|
+
// when every roster entry declares its own target, making the adapter-owned topology explicit. But when
|
|
55
|
+
// `subject.topology: shared-world` is also declared, N participants against one public target is the
|
|
56
|
+
// external-public shared-world topology (#164 phase 2), so route it there (a real public deployment
|
|
57
57
|
// as the shared plane) instead of refusing; externalPublicSharedWorldValidationReason then applies.
|
|
58
58
|
if (participantCount > 1 &&
|
|
59
59
|
config.policies?.allowPublicTargets === true &&
|
|
@@ -107,9 +107,9 @@ export function sharedWorldValidationReason(config) {
|
|
|
107
107
|
: concurrentSharedWorldValidationReason(config);
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
* The structural checks every provisioned shared world shares. It
|
|
110
|
+
* The structural checks every provisioned shared world shares. It requires: a clone or local-tree source + e2b-desktop
|
|
111
111
|
* target + a computer-use actor + a `subject.serve` block + an `actors[0].lanes` roster of ≥2 roles (the
|
|
112
|
-
* roster
|
|
112
|
+
* roster is the role roster; there is no separate roles[] field), and every role `entry` must resolve
|
|
113
113
|
* same-origin (loopback) with serve.url. Fail-closed: a half-declared shared-world is rejected,
|
|
114
114
|
* never silently downgraded.
|
|
115
115
|
*/
|
|
@@ -263,7 +263,7 @@ export function outputTokenLimitValidationReason(config) {
|
|
|
263
263
|
* Shared-world participants share one live app, so at least two must be live at once. The
|
|
264
264
|
* sequential shared-world route (`execution.concurrency: 1`) was removed in 0.106.0; the parser
|
|
265
265
|
* fills an omitted concurrency with the participant count. Both callers check it after their
|
|
266
|
-
* two-
|
|
266
|
+
* two-participant roster floor, so a one-seat roster gets the roster refusal, never this one.
|
|
267
267
|
*/
|
|
268
268
|
function sharedWorldConcurrencyReason(config) {
|
|
269
269
|
// Direct library callers skip the parser, so an omitted value defaults here exactly as the
|
|
@@ -275,11 +275,11 @@ function sharedWorldConcurrencyReason(config) {
|
|
|
275
275
|
return `shared-world labs need \`execution.concurrency\` of at least 2 (got ${concurrency}). Sequential shared-world turns (concurrency 1) were removed in 0.106.0: omit execution.concurrency to run every participant at once, or set it to 2 or more. A provisioned subject also needs \`subject.exposure: synthetic\` and a \`serve.start\` that binds 0.0.0.0.`;
|
|
276
276
|
}
|
|
277
277
|
/**
|
|
278
|
-
* Cross-validate a
|
|
279
|
-
* or null when valid. Includes the base shared-world checks
|
|
280
|
-
* subject attestation
|
|
281
|
-
* all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (
|
|
282
|
-
* orphan actor sandboxes). Enforced at parse
|
|
278
|
+
* Cross-validate a concurrent shared-world declaration (#164 phase 2). Returns the failure message,
|
|
279
|
+
* or null when valid. Includes the base shared-world checks plus the concurrent extras: a synthetic
|
|
280
|
+
* subject attestation, a 0.0.0.0 serve bind (getHost only routes to a port bound on
|
|
281
|
+
* all interfaces), and no `subject.clone.keep`/`subject.localTree.keep` (either would
|
|
282
|
+
* orphan actor sandboxes). Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld
|
|
283
283
|
* is exported npm surface).
|
|
284
284
|
*/
|
|
285
285
|
export function concurrentSharedWorldValidationReason(config) {
|
|
@@ -304,15 +304,15 @@ export function concurrentSharedWorldValidationReason(config) {
|
|
|
304
304
|
return null;
|
|
305
305
|
}
|
|
306
306
|
/**
|
|
307
|
-
* Cross-validate the
|
|
308
|
-
* deployment used
|
|
309
|
-
* The
|
|
310
|
-
* it
|
|
311
|
-
* are inert with no sandbox
|
|
307
|
+
* Cross-validate the external-public shared-world declaration (#164 phase 2): a real public
|
|
308
|
+
* deployment used directly as the shared plane (no getHost, no clone, no subject sandbox, no seed).
|
|
309
|
+
* The counterpart of concurrentSharedWorldValidationReason for a plane the harness does not own:
|
|
310
|
+
* it rejects every provisioned-subject field (serve/state.seed/state.checkpoint/exposure/clone/repos
|
|
311
|
+
* are inert with no sandbox, so they fail closed per invariant 6), and requires a
|
|
312
312
|
* non-loopback appUrl + allowPublicTargets + the operator-ownership attestation subject.publicTarget +
|
|
313
|
-
* concurrency >= 2 + an actors[0].lanes roster of ≥2 with
|
|
313
|
+
* concurrency >= 2 + an actors[0].lanes roster of ≥2 with exactly one host participant. The getHost synthetic
|
|
314
314
|
* gate is deliberately unreachable here (there is no internet-reachable harness-owned URL to attest).
|
|
315
|
-
* Enforced at parse
|
|
315
|
+
* Enforced at parse and re-enforced in the engine (runConcurrentSharedWorld is exported npm surface).
|
|
316
316
|
*/
|
|
317
317
|
export function externalPublicSharedWorldValidationReason(config) {
|
|
318
318
|
const structuralReason = rosterStructuralValidationReason(config);
|
|
@@ -343,13 +343,13 @@ export function externalPublicSharedWorldValidationReason(config) {
|
|
|
343
343
|
return "the external-public shared-world route requires a non-loopback http(s) `subject.appUrl` — a loopback URL is not a shared public plane (use the getHost provisioned route for a local subject).";
|
|
344
344
|
}
|
|
345
345
|
// The operator-ownership attestation (the honest analog of exposure: synthetic — you cannot claim
|
|
346
|
-
// synthetic on a real site, but you
|
|
346
|
+
// synthetic on a real site, but you must attest you own/operate it). Author-trust; unverifiable.
|
|
347
347
|
if (config.subject.publicTarget?.authorized !== true) {
|
|
348
348
|
return "the external-public shared-world route requires `subject.publicTarget: { owner, authorized: true }` — you must attest you own/operate the public deployment used as the shared plane (author-trust; the harness cannot verify ownership).";
|
|
349
349
|
}
|
|
350
|
-
//
|
|
350
|
+
// No provisioned-subject field is allowed: with no sandbox they cannot act, so they are rejected
|
|
351
351
|
// with a precise reason, never silently ignored (invariant 6). exposure: synthetic in particular
|
|
352
|
-
// would be a
|
|
352
|
+
// would be a false claim on a real site (the harness neither provisioned nor exposed it).
|
|
353
353
|
if (config.subject.exposure !== undefined) {
|
|
354
354
|
return "`subject.exposure: synthetic` is forbidden on the external-public shared-world route — you cannot attest a real public deployment is synthetic seeded data; use `subject.publicTarget` to attest ownership instead.";
|
|
355
355
|
}
|
package/dist/lab/warnings.js
CHANGED
|
@@ -12,13 +12,14 @@ const scriptedRoute = (routes) => !promptRoute(routes) && routes.scripted;
|
|
|
12
12
|
const otherRoute = (routes) => !promptRoute(routes) && !routes.scripted;
|
|
13
13
|
/** Rows for each actor, reported as `actors[<index>].<field>`, in this order per actor. */
|
|
14
14
|
const ACTOR_ROWS = [
|
|
15
|
-
// Shared-world
|
|
15
|
+
// Shared-world-only fields on the roster: a participant's `entry` is inert anywhere else
|
|
16
|
+
// (invariant 6).
|
|
16
17
|
{
|
|
17
18
|
field: "lanes[].entry",
|
|
18
|
-
reason: "the per-
|
|
19
|
+
reason: "the per-participant loopback entry is a shared-world capability; needs subject.topology: shared-world",
|
|
19
20
|
applies: (actor, routes) => Boolean(rosterOf(actor)?.some((entry) => entry.entry !== undefined)) && !routes.shared,
|
|
20
21
|
},
|
|
21
|
-
// The host-seat marker acts
|
|
22
|
+
// The host-seat marker acts only on the external-public shared-world route; inert elsewhere.
|
|
22
23
|
{
|
|
23
24
|
field: "lanes[].host",
|
|
24
25
|
reason: "the designated host-participant marker; needs the external-public shared-world route: app-url × topology shared-world × allowPublicTargets",
|
|
@@ -57,7 +58,7 @@ const ACTOR_ROWS = [
|
|
|
57
58
|
reason: "the scripted-browser route fans out via actors[0].count, not an actors[0].lanes roster",
|
|
58
59
|
applies: (actor, routes) => scriptedRoute(routes) && Boolean(rosterOf(actor)),
|
|
59
60
|
},
|
|
60
|
-
// On every other route the prompt fields, persona and the
|
|
61
|
+
// On every other route the prompt fields, persona and the `lanes[]` roster are inert.
|
|
61
62
|
{ field: "mission", applies: (actor, routes) => otherRoute(routes) && Boolean(actor.mission) },
|
|
62
63
|
{
|
|
63
64
|
field: "laneFocus",
|
|
@@ -89,7 +90,7 @@ const CONFIG_ROWS = [
|
|
|
89
90
|
field: "subject.state",
|
|
90
91
|
applies: (config, routes) => Boolean(config.subject.state) && !routes.cua && !routes.scripted,
|
|
91
92
|
},
|
|
92
|
-
// topology + checkpoint act
|
|
93
|
+
// topology + checkpoint act only on the shared-world route (#164); a set-but-unconsumed value
|
|
93
94
|
// (incl. an explicit per-lane-worlds, which the cua route already is by mechanism) warns inert.
|
|
94
95
|
{
|
|
95
96
|
field: "subject.topology",
|
|
@@ -101,14 +102,14 @@ const CONFIG_ROWS = [
|
|
|
101
102
|
reason: "the shared-world state-checkpoint probe; needs subject.topology: shared-world",
|
|
102
103
|
applies: (config, routes) => config.subject.state?.checkpoint !== undefined && !routes.shared,
|
|
103
104
|
},
|
|
104
|
-
// publicTarget (the external-public ownership attestation) acts
|
|
105
|
+
// publicTarget (the external-public ownership attestation) acts only on the external-public
|
|
105
106
|
// shared-world route; inert elsewhere. (It is already parse-rejected on non-app-url sources.)
|
|
106
107
|
{
|
|
107
108
|
field: "subject.publicTarget",
|
|
108
109
|
reason: "the external-public ownership attestation; needs the external-public shared-world route: app-url × topology shared-world × allowPublicTargets",
|
|
109
110
|
applies: (config, routes) => config.subject.publicTarget !== undefined && !routes.externalPublic,
|
|
110
111
|
},
|
|
111
|
-
// exposure (the synthetic-subject attestation) acts
|
|
112
|
+
// exposure (the synthetic-subject attestation) acts only on the shared-world route (the
|
|
112
113
|
// getHost-exposed plane) and on scripted clones; inert elsewhere.
|
|
113
114
|
{
|
|
114
115
|
field: "subject.exposure",
|
|
@@ -117,7 +118,7 @@ const CONFIG_ROWS = [
|
|
|
117
118
|
!routes.shared &&
|
|
118
119
|
!(routes.scripted && config.subject.source === "clone"),
|
|
119
120
|
},
|
|
120
|
-
// comms.email drives the in-sandbox email/SMS catch, which needs a subject sandbox
|
|
121
|
+
// comms.email drives the in-sandbox email/SMS catch, which needs a subject sandbox that humanish
|
|
121
122
|
// provisions (clone or local-tree) so it holds a handle to host the catch. On an app-url /
|
|
122
123
|
// operator-provided subject there is no such handle, so a declared comms block would silently
|
|
123
124
|
// collect nothing — a false green. Warn at parse time (fires on inspect + dry-run too).
|
|
@@ -138,8 +139,8 @@ const CONFIG_ROWS = [
|
|
|
138
139
|
applies: (config) => Boolean(config.comms?.email?.external) &&
|
|
139
140
|
(config.subject.source === "clone" || config.subject.source === "local-tree"),
|
|
140
141
|
},
|
|
141
|
-
// clone.keep
|
|
142
|
-
// a failed install/boot; otherwise always killed). clone.fanout is
|
|
142
|
+
// clone.keep is consumed on the cua route (honored on failure: the sandbox is left up to debug
|
|
143
|
+
// a failed install/boot; otherwise always killed). clone.fanout is rejected on the cua route
|
|
143
144
|
// (a hard parse error above), so it can never reach this warning list there.
|
|
144
145
|
{
|
|
145
146
|
field: "execution.timeoutMs",
|
|
@@ -152,13 +153,13 @@ const CONFIG_ROWS = [
|
|
|
152
153
|
field: "execution.completionTimeoutMs",
|
|
153
154
|
applies: (config) => config.execution?.completionTimeoutMs !== undefined,
|
|
154
155
|
},
|
|
155
|
-
// execution.concurrency is
|
|
156
|
+
// execution.concurrency is consumed on the cua route (it bounds in-flight fan-out participants);
|
|
156
157
|
// inert (warned) everywhere else.
|
|
157
158
|
{
|
|
158
159
|
field: "execution.concurrency",
|
|
159
160
|
applies: (config, routes) => config.execution?.concurrency !== undefined && !routes.cua,
|
|
160
161
|
},
|
|
161
|
-
// execution.caps is
|
|
162
|
+
// execution.caps is consumed on the cua route (maxUsd is the fail-closed spend abort); inert
|
|
162
163
|
// (warned) everywhere else so a misplaced budget field is never trusted to cap a route it cannot.
|
|
163
164
|
{
|
|
164
165
|
field: "execution.caps",
|
|
@@ -167,7 +168,7 @@ const CONFIG_ROWS = [
|
|
|
167
168
|
},
|
|
168
169
|
// terminal-product consumes subject.product, scenario.caps, execution.{terminal,runtimeAuth}:
|
|
169
170
|
// dry-run records the contract; live execution enforces caps and command-scoped auth. On every
|
|
170
|
-
//
|
|
171
|
+
// other route they are inert and must warn so a
|
|
171
172
|
// misplaced safety/budget field is never trusted to do something it cannot (invariant 6).
|
|
172
173
|
{
|
|
173
174
|
field: "subject.product",
|
|
@@ -227,9 +228,9 @@ const CONFIG_ROWS = [
|
|
|
227
228
|
field: "execution.desktop.sandboxTimeoutMs",
|
|
228
229
|
applies: (config, routes) => !routes.cua && config.execution?.desktop?.sandboxTimeoutMs !== undefined,
|
|
229
230
|
},
|
|
230
|
-
// execution.desktop.template (the custom E2B desktop image) is consumed
|
|
231
|
+
// execution.desktop.template (the custom E2B desktop image) is consumed only where a desktop is
|
|
231
232
|
// actually created via Sandbox.create — the e2b-desktop computer-use routes (cua/shared-world/
|
|
232
|
-
// concurrent). It is
|
|
233
|
+
// concurrent). It is inert on every other route (incl. the in-process local-app cua route, which
|
|
233
234
|
// creates no desktop): warn so an unconsumed template is never silently ignored (invariant 6).
|
|
234
235
|
{
|
|
235
236
|
field: "execution.desktop.template",
|
|
@@ -243,7 +244,7 @@ const CONFIG_ROWS = [
|
|
|
243
244
|
reason: "no current route reads it",
|
|
244
245
|
applies: (config) => config.execution?.desktop?.codexAppServer !== undefined,
|
|
245
246
|
},
|
|
246
|
-
// scenario.ref is
|
|
247
|
+
// scenario.ref is consumed on the scripted-browser route (required there); forward-declared
|
|
247
248
|
// everywhere else.
|
|
248
249
|
{
|
|
249
250
|
field: "scenario.ref",
|
|
@@ -251,7 +252,7 @@ const CONFIG_ROWS = [
|
|
|
251
252
|
},
|
|
252
253
|
{ field: "scenario.inline", applies: (config) => Boolean(config.scenario?.inline) },
|
|
253
254
|
// review.{scoring,milestones,vocabulary} stay forward-declared (reserved for #319) on every route.
|
|
254
|
-
// review.scorer (#316)
|
|
255
|
+
// review.scorer (#316) is consumed (loaded + wired, or fail-closed at load) on every scorer-capable
|
|
255
256
|
// route, so it does not warn there; on the scripted-browser route the actor carries no scorer seam,
|
|
256
257
|
// so a declared scorer is flagged inert (the run also fails closed at load).
|
|
257
258
|
{
|
|
@@ -297,7 +298,7 @@ function rowLabel(row, prefix = "") {
|
|
|
297
298
|
: `${prefix}${row.field} (${row.reason})`;
|
|
298
299
|
}
|
|
299
300
|
// Report fields that are present but not yet consumed by the engine, so a user never trusts a
|
|
300
|
-
// setting that silently does nothing. Keeps the schema forward-correct
|
|
301
|
+
// setting that silently does nothing. Keeps the schema forward-correct and honest.
|
|
301
302
|
export function forwardDeclaredWarnings(config) {
|
|
302
303
|
const routes = routesOf(config);
|
|
303
304
|
const inert = [];
|
|
@@ -324,7 +325,7 @@ export function forwardDeclaredWarnings(config) {
|
|
|
324
325
|
warnings.push(`execution.concurrency ${cap} caps a ${participantCount}-participant roster: participants run in waves of ${cap}, never all live at once. Remove execution.concurrency (the default runs all ${participantCount} participants simultaneously) or set it to ${participantCount}; declare a lower cap only to bound simultaneous paid desktops.`);
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
|
-
// Partial email coverage is legal but loud (#351): a
|
|
328
|
+
// Partial email coverage is legal but loud (#351): a participant without an addressed recipient never
|
|
328
329
|
// hears an inbox exists, so an email-gated flow on that seat dead-ends by construction.
|
|
329
330
|
if (routes.cua && config.comms?.email?.recipients) {
|
|
330
331
|
const participantIds = declaredParticipantIds(config);
|
|
@@ -3,7 +3,7 @@ import { type ObserverData } from "./data.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Resolve — and in a repo checkout, build — the Observer artifact BEFORE any run or
|
|
5
5
|
* lab work starts. A missing artifact must cost seconds at startup, never a completed
|
|
6
|
-
* session (a live
|
|
6
|
+
* session (a live participant spends real money before the render step would have noticed).
|
|
7
7
|
* Unconditional on purpose: the artifact is the only renderer now, so the fail-before-
|
|
8
8
|
* spend property this preflight bought under the flag matters more, not less.
|
|
9
9
|
*/
|
|
@@ -5,7 +5,7 @@ import { execSync } from "node:child_process";
|
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { projectShareCheckedAnalysis,
|
|
8
|
+
import { projectShareCheckedAnalysis, analysisSharingProblems } from "../analysis/sharing.js";
|
|
9
9
|
import { withObserverEndings } from "./data.js";
|
|
10
10
|
const OBSERVER_DATA_PLACEHOLDER = "__HUMANISH_OBSERVER_DATA__";
|
|
11
11
|
const OBSERVER_DATA_SLOT = `<script id="observer-data" type="application/json">${OBSERVER_DATA_PLACEHOLDER}</script>`;
|
|
@@ -13,7 +13,7 @@ let cachedObserverArtifact = null;
|
|
|
13
13
|
/**
|
|
14
14
|
* Resolve — and in a repo checkout, build — the Observer artifact BEFORE any run or
|
|
15
15
|
* lab work starts. A missing artifact must cost seconds at startup, never a completed
|
|
16
|
-
* session (a live
|
|
16
|
+
* session (a live participant spends real money before the render step would have noticed).
|
|
17
17
|
* Unconditional on purpose: the artifact is the only renderer now, so the fail-before-
|
|
18
18
|
* spend property this preflight bought under the flag matters more, not less.
|
|
19
19
|
*/
|
|
@@ -192,7 +192,7 @@ export function renderObserverHtml(data, options = {}) {
|
|
|
192
192
|
},
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
|
-
const sharing =
|
|
195
|
+
const sharing = analysisSharingProblems(analysis);
|
|
196
196
|
if (data.publicSafety && (sharing.sensitive || sharing.unverified)) {
|
|
197
197
|
const share = data.publicSafety.share;
|
|
198
198
|
data = {
|
package/dist/observer/data.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { actorEnding } from "../actors/stop-cause.js";
|
|
2
2
|
import { isCommsReceivingEvidence, receivingAnalysisContext } from "../comms/receiving-evidence.js";
|
|
3
|
-
import { formatParticipantOutcomes,
|
|
3
|
+
import { formatParticipantOutcomes, formatRunTaskFunnel, participantOutcomeDetails, withCuaReviewProvenance, } from "../run/outcomes.js";
|
|
4
4
|
import { cuaGoalSource, CUA_COMPLETION_NOTE } from "../actors/goal-source.js";
|
|
5
5
|
export const OBSERVER_DATA_SCHEMA = "humanish.observer-data.v1";
|
|
6
6
|
/** Discard a forged or stale runtime grant before projecting persisted evidence. */
|
|
@@ -95,7 +95,7 @@ export function buildObserverData(bundle, generatedAt = new Date().toISOString()
|
|
|
95
95
|
? {}
|
|
96
96
|
: {
|
|
97
97
|
tasks: bundle.review.tasks,
|
|
98
|
-
tasksLine:
|
|
98
|
+
tasksLine: formatRunTaskFunnel(bundle.review.tasks),
|
|
99
99
|
}),
|
|
100
100
|
},
|
|
101
101
|
summary: {
|
package/dist/observer/render.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createServer } from "node:http";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import { projectShareCheckedAnalysis } from "../analysis/sharing.js";
|
|
8
|
-
import {
|
|
8
|
+
import { loadAnalysis } from "../analysis/load.js";
|
|
9
9
|
import { physicalCwdOf, runIdOf, bindExistingRunArtifactPaths, isSafeRunIdSegment, resolveLatestRunDirectory, validatePreparedRunArtifactPaths, } from "../run/paths.js";
|
|
10
10
|
import { writeContainedOutputFile } from "../run/contained-output.js";
|
|
11
11
|
import { loadRunBundlePrepared } from "../run/locate.js";
|
|
@@ -87,7 +87,7 @@ export async function renderObserver(cwdInput, runInput, options = {}) {
|
|
|
87
87
|
throw new Error("Observer output directory does not match the selected run.");
|
|
88
88
|
}
|
|
89
89
|
const observerPath = path.join(preparedRunPaths.physicalRunRoot, "observer", "index.html");
|
|
90
|
-
const analysis = projectShareCheckedAnalysis(await
|
|
90
|
+
const analysis = projectShareCheckedAnalysis(await loadAnalysis(preparedRunPaths));
|
|
91
91
|
const observerData = buildObserverData(loaded.bundle);
|
|
92
92
|
observerData.publicSafety.share = {
|
|
93
93
|
status: verified.shareSafety.status,
|
|
@@ -4,7 +4,7 @@ import { type PinnedDirectory } from "./pinned-files.js";
|
|
|
4
4
|
export interface ObserverRuntimeStreamUrl {
|
|
5
5
|
streamId: string;
|
|
6
6
|
url: string;
|
|
7
|
-
/** Set when the
|
|
7
|
+
/** Set when the participant's sandbox is gone (finished or torn down). An ended stream's live URL is a
|
|
8
8
|
* dead noVNC page — the overlay stops injecting it so the tile falls back to the recorded
|
|
9
9
|
* evidence (keyframe replay/screenshot) instead of rendering "sandbox not found" (#357). */
|
|
10
10
|
ended?: boolean;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// URLs, its analysis, and its media with byte ranges. serveObserver (render.ts) and the library
|
|
3
3
|
// server (serve.ts) both route requests through them.
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { isAnalysisRecordPath, projectShareCheckedAnalysis } from "../analysis/sharing.js";
|
|
6
|
+
import { loadAnalysis } from "../analysis/load.js";
|
|
7
7
|
import { listRuns } from "../run/stored-runs.js";
|
|
8
8
|
import { bindExistingRunArtifactPaths, isPathInside, isSafeRunIdSegment } from "../run/paths.js";
|
|
9
9
|
import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, isRunStatusRecord } from "../run/status.js";
|
|
@@ -23,7 +23,7 @@ async function readObserverAnalysis(runRoot) {
|
|
|
23
23
|
prepared.runRootIdentity.ino !== runRoot.ino) {
|
|
24
24
|
throw new Error("ANALYSIS_STORAGE_CHANGED");
|
|
25
25
|
}
|
|
26
|
-
return projectShareCheckedAnalysis(await
|
|
26
|
+
return projectShareCheckedAnalysis(await loadAnalysis(prepared));
|
|
27
27
|
}
|
|
28
28
|
catch {
|
|
29
29
|
return {
|
|
@@ -51,7 +51,7 @@ export async function serveRunPath(runRoot, relativePath, response, runtimeStrea
|
|
|
51
51
|
const derivedLeaf = path.posix.basename(cleanedRelativePath);
|
|
52
52
|
if (derivedRoot === ".analysis-lock" ||
|
|
53
53
|
derivedLeaf.startsWith(".humanish-write-") ||
|
|
54
|
-
|
|
54
|
+
isAnalysisRecordPath(cleanedRelativePath)) {
|
|
55
55
|
writeResponse(response, 404, "Not found", "text/plain; charset=utf-8");
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
@@ -148,7 +148,7 @@ async function withLocalRunStatus(runRoot, input) {
|
|
|
148
148
|
if (record.state === "finished") {
|
|
149
149
|
state = "finished";
|
|
150
150
|
}
|
|
151
|
-
else if (now - updated <= RUN_STATUS_STALE_MS) {
|
|
151
|
+
else if (record.state === "running" && now - updated <= RUN_STATUS_STALE_MS) {
|
|
152
152
|
state = "running";
|
|
153
153
|
}
|
|
154
154
|
}
|
package/dist/observer/serve.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ export interface ServeResult {
|
|
|
28
28
|
};
|
|
29
29
|
runsListed: number;
|
|
30
30
|
shareReadyCount?: number;
|
|
31
|
+
/** With --safe: the runs left out, grouped by grade and reasons. */
|
|
32
|
+
hiddenRuns?: HiddenRunGroup[];
|
|
31
33
|
entryRunId?: string;
|
|
32
34
|
opened?: boolean;
|
|
33
35
|
openCommand?: string;
|
|
@@ -46,9 +48,22 @@ interface ServeControlPlane {
|
|
|
46
48
|
runId?: string;
|
|
47
49
|
}>;
|
|
48
50
|
}
|
|
51
|
+
/** Why verify kept a run out of a share-safe library: its grade and reason codes. */
|
|
52
|
+
interface ShareRefusal {
|
|
53
|
+
status: string;
|
|
54
|
+
reasons: string[];
|
|
55
|
+
}
|
|
56
|
+
/** Runs a share-safe library left out for the same grade and reasons. */
|
|
57
|
+
export interface HiddenRunGroup {
|
|
58
|
+
status: string;
|
|
59
|
+
reasons: string[];
|
|
60
|
+
runs: number;
|
|
61
|
+
}
|
|
49
62
|
export interface ShareSafetyAdmission {
|
|
50
63
|
/** The files verify found share_ready, or null when the run is not admitted. */
|
|
51
64
|
admit(runId: string): Promise<AdmittedRun | null>;
|
|
65
|
+
/** Why verify refused the run, after admit returned null for it; undefined otherwise. */
|
|
66
|
+
refusal(runId: string): ShareRefusal | undefined;
|
|
52
67
|
}
|
|
53
68
|
export declare function createShareSafetyAdmission(cwd: string, options?: {
|
|
54
69
|
verifyImpl?: typeof verifyRun;
|
|
@@ -79,6 +94,8 @@ export interface ServeLibraryServer {
|
|
|
79
94
|
mode: ServeMode;
|
|
80
95
|
runsListed: number;
|
|
81
96
|
shareReadyCount?: number;
|
|
97
|
+
/** With safe: the runs left out, grouped by grade and reasons. */
|
|
98
|
+
hiddenRuns?: HiddenRunGroup[];
|
|
82
99
|
entryRunId?: string;
|
|
83
100
|
addPublicOrigin(origin: string): void;
|
|
84
101
|
close(): Promise<void>;
|
package/dist/observer/serve.js
CHANGED
|
@@ -19,11 +19,17 @@ export function createShareSafetyAdmission(cwd, options = {}) {
|
|
|
19
19
|
// content hash at read time, which drops the entry.
|
|
20
20
|
const cache = new Map();
|
|
21
21
|
const shareReady = (verified) => verified.ok === true && verified.shareSafety.status === "share_ready";
|
|
22
|
-
const verifyAdmission = async (runId, runDirectory, before, forget) => {
|
|
22
|
+
const verifyAdmission = async (runId, runDirectory, before, entry, forget) => {
|
|
23
23
|
// A run verify refuses is never served, so its bytes are never hashed. Hashing reads every
|
|
24
24
|
// byte, and one large file in a refused run would otherwise cost startup time for nothing.
|
|
25
|
-
|
|
25
|
+
const verified = await verifyImpl(cwd, runId);
|
|
26
|
+
if (!shareReady(verified)) {
|
|
27
|
+
entry.refusal = {
|
|
28
|
+
status: verified.shareSafety.status === "share_ready" ? "blocked" : verified.shareSafety.status,
|
|
29
|
+
reasons: verified.shareSafety.reasons.map((reason) => reason.code),
|
|
30
|
+
};
|
|
26
31
|
return null;
|
|
32
|
+
}
|
|
27
33
|
// Admitted: hash, verify again, and hash after, so the served bytes are the ones verify scanned.
|
|
28
34
|
const hashesBefore = await hashRunInventory(runDirectory, before);
|
|
29
35
|
if (!hashesBefore)
|
|
@@ -62,12 +68,31 @@ export function createShareSafetyAdmission(cwd, options = {}) {
|
|
|
62
68
|
if (cache.get(runId) === entry)
|
|
63
69
|
cache.delete(runId);
|
|
64
70
|
};
|
|
65
|
-
entry.admitted = verifyAdmission(runId, runDirectory, before, forget).catch(() =>
|
|
71
|
+
entry.admitted = verifyAdmission(runId, runDirectory, before, entry, forget).catch(() => {
|
|
72
|
+
entry.refusal = { status: "unverifiable", reasons: ["VERIFY_FAILED"] };
|
|
73
|
+
return null;
|
|
74
|
+
});
|
|
66
75
|
cache.set(runId, entry);
|
|
67
76
|
return entry.admitted;
|
|
68
77
|
},
|
|
78
|
+
refusal(runId) {
|
|
79
|
+
return cache.get(runId)?.refusal;
|
|
80
|
+
},
|
|
69
81
|
};
|
|
70
82
|
}
|
|
83
|
+
/** The refused runs grouped by grade and reasons, the largest group first. */
|
|
84
|
+
function hiddenRunGroups(refusals) {
|
|
85
|
+
const groups = new Map();
|
|
86
|
+
for (const refusal of refusals) {
|
|
87
|
+
const key = `${refusal.status}\0${refusal.reasons.join(",")}`;
|
|
88
|
+
const group = groups.get(key);
|
|
89
|
+
if (group)
|
|
90
|
+
group.runs += 1;
|
|
91
|
+
else
|
|
92
|
+
groups.set(key, { ...refusal, runs: 1 });
|
|
93
|
+
}
|
|
94
|
+
return [...groups.values()].sort((left, right) => right.runs - left.runs);
|
|
95
|
+
}
|
|
71
96
|
function sameHashes(left, right) {
|
|
72
97
|
return left.size === right.size && [...left].every(([key, hash]) => right.get(key) === hash);
|
|
73
98
|
}
|
|
@@ -215,10 +240,15 @@ export async function serveObserverLibrary(cwdInput, options) {
|
|
|
215
240
|
const allRuns = (await listRuns(cwd)).runs;
|
|
216
241
|
let runsListed;
|
|
217
242
|
let shareReadyCount;
|
|
243
|
+
let hiddenRuns;
|
|
218
244
|
if (options.safe) {
|
|
219
245
|
const admitted = await Promise.all(allRuns.map((run) => admission.admit(run.runId)));
|
|
220
246
|
shareReadyCount = admitted.filter((run) => run !== null).length;
|
|
221
247
|
runsListed = shareReadyCount;
|
|
248
|
+
// A run refused before verify ran, such as one whose files cannot be listed, is unverifiable.
|
|
249
|
+
hiddenRuns = hiddenRunGroups(allRuns
|
|
250
|
+
.filter((_run, index) => admitted[index] === null)
|
|
251
|
+
.map((run) => admission.refusal(run.runId) ?? { status: "unverifiable", reasons: ["VERIFY_FAILED"] }));
|
|
222
252
|
}
|
|
223
253
|
else {
|
|
224
254
|
runsListed = allRuns.length;
|
|
@@ -266,6 +296,7 @@ export async function serveObserverLibrary(cwdInput, options) {
|
|
|
266
296
|
mode,
|
|
267
297
|
runsListed,
|
|
268
298
|
...(shareReadyCount !== undefined ? { shareReadyCount } : {}),
|
|
299
|
+
...(hiddenRuns !== undefined ? { hiddenRuns } : {}),
|
|
269
300
|
...(entryRunId ? { entryRunId } : {}),
|
|
270
301
|
// A tunnel's public origin is only known after the tunnel starts (post bind); this lets the
|
|
271
302
|
// caller declare it, extending the Host allowlist so the authenticated edge forwarding under
|
|
@@ -34,7 +34,7 @@ export declare function participantFeedbackCandidates(args: {
|
|
|
34
34
|
commsArtifactPath?: string;
|
|
35
35
|
}>;
|
|
36
36
|
}): RunFeedbackCandidate[];
|
|
37
|
-
/** Human-readable provenance line for the single-
|
|
37
|
+
/** Human-readable provenance line for the single-participant subject.provenance event (invariant 5):
|
|
38
38
|
* claims "cloned/packed and served" ONLY when it actually happened. */
|
|
39
39
|
export declare function subjectProvenanceMessage(provenance: CuaSubjectProvenanceArg, publicAppUrl: string, dryRun: boolean, hasSession: boolean): string;
|
|
40
40
|
export declare function providerResourcesForOutcome(args: {
|
|
@@ -109,7 +109,7 @@ export function participantFeedbackCandidates(args) {
|
|
|
109
109
|
}
|
|
110
110
|
return candidates;
|
|
111
111
|
}
|
|
112
|
-
/** Human-readable provenance line for the single-
|
|
112
|
+
/** Human-readable provenance line for the single-participant subject.provenance event (invariant 5):
|
|
113
113
|
* claims "cloned/packed and served" ONLY when it actually happened. */
|
|
114
114
|
export function subjectProvenanceMessage(provenance, publicAppUrl, dryRun, hasSession) {
|
|
115
115
|
if (provenance.source === "clone") {
|
|
@@ -149,14 +149,21 @@ export function providerResourcesForOutcome(args) {
|
|
|
149
149
|
kind: "sandbox",
|
|
150
150
|
id: args.outcome.sandboxId,
|
|
151
151
|
owner: "humanish",
|
|
152
|
-
|
|
152
|
+
// Only a sandbox kept on purpose is known to be running; an unconfirmed release may or may
|
|
153
|
+
// not have stopped it.
|
|
154
|
+
status: args.outcome.killed
|
|
155
|
+
? "killed"
|
|
156
|
+
: args.outcome.sandboxRelease?.state === "retained"
|
|
157
|
+
? "running"
|
|
158
|
+
: "unknown",
|
|
153
159
|
...participantResourceIds(args.ids, args.participantId),
|
|
154
160
|
createdAt: args.createdAt,
|
|
155
161
|
cleanup: {
|
|
156
162
|
killed: args.outcome.killed,
|
|
157
163
|
reason: args.outcome.killed
|
|
158
164
|
? "killed during normal participant teardown"
|
|
159
|
-
:
|
|
165
|
+
: (args.outcome.sandboxRelease?.warning ??
|
|
166
|
+
"not killed during normal participant teardown; cleanup may reclaim by exact recorded id"),
|
|
160
167
|
},
|
|
161
168
|
},
|
|
162
169
|
];
|