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
|
@@ -1,48 +1,31 @@
|
|
|
1
1
|
import type { ActorCompletionReason, ActorStatus } from "../../actors/contract.js";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { AutomaticAnalysisHooks, AutomaticAnalysisResult } from "../../analysis/automatic-completion.js";
|
|
2
|
+
import type { LabEvent } from "../../lab/run-lab-events.js";
|
|
3
|
+
import type { AutomaticAnalysisResult } from "../../analysis/automatic-completion.js";
|
|
5
4
|
import type { LabConfig } from "../../lab/types.js";
|
|
6
|
-
import {
|
|
5
|
+
import type { ObserverResult } from "../../observer/render.js";
|
|
7
6
|
import type { RunSubjectProvenance } from "../../run/bundle.js";
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
10
|
-
import type { E2BDesktopModule, E2BDesktopSandbox } from "../../substrates/e2b/sdk.js";
|
|
7
|
+
import type { LabDeps } from "../../lab/lab-deps.js";
|
|
8
|
+
import type { RunLabHomes } from "../../lab/run-lab-homes.js";
|
|
11
9
|
export declare const SCRIPTED_BROWSER_LAB_SCHEMA = "humanish.scripted-lab-result.v1";
|
|
12
|
-
/**
|
|
13
|
-
* Library-level hooks: DI seams so CI drives the full path (real engine, real projection)
|
|
14
|
-
* with a fake browser at zero spend, plus the production browser resolution override.
|
|
15
|
-
*/
|
|
16
|
-
export interface ScriptedBrowserLabHooks {
|
|
17
|
-
runSession?: (options: ScriptedBrowserSessionOptions) => Promise<ScriptedBrowserSessionResult>;
|
|
18
|
-
/** Injected browser factory — forwarded to every session; skips browser-binary resolution. */
|
|
19
|
-
launchBrowser?: (args: ScriptedBrowserLaunchArgs) => Promise<ScriptedBrowserLike>;
|
|
20
|
-
/** Test/library env seam; CLI passes process.env. Values are scrubbed, names only persist. */
|
|
21
|
-
env?: Record<string, string | undefined>;
|
|
22
|
-
/** E2B DI seam for clone × e2b-desktop × scripted-browser. */
|
|
23
|
-
loadDesktopModule?: () => Promise<E2BDesktopModule>;
|
|
24
|
-
/** Optional adopter hook after subject sandbox creation, before clone provisioning. */
|
|
25
|
-
prepareDesktop?: (desktop: E2BDesktopSandbox) => Promise<void>;
|
|
26
|
-
/** Detached-step timers for deterministic tests around clone/seed/start provisioning. */
|
|
27
|
-
detachedTimers?: DetachedTimers;
|
|
28
|
-
/** Override the resolved browser binary (tests; operators use HUMANISH_BROWSER_COMMAND). */
|
|
29
|
-
browserCommand?: string;
|
|
30
|
-
renderObserverFn?: typeof renderObserver;
|
|
31
|
-
now?: () => number;
|
|
32
|
-
}
|
|
33
10
|
/** What a scripted run takes besides its plan. The plan carries the config, dry run and lab. */
|
|
34
11
|
export type ScriptedRunInput = Omit<RunScriptedBrowserLabOptions, "config" | "dryRun" | "lab">;
|
|
35
12
|
export interface RunScriptedBrowserLabOptions {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
13
|
+
/** Cancels post-run analysis only. */
|
|
14
|
+
analysisSignal?: AbortSignal;
|
|
15
|
+
/** Reports the analysis window to onEvent; built by normalizeRunLabOptions. */
|
|
16
|
+
emit?: (event: LabEvent) => void;
|
|
39
17
|
cwd: string;
|
|
40
18
|
config: LabConfig;
|
|
41
19
|
/** Resolved upstream (scenario.mode + CLI override); defaults safe (dry-run). */
|
|
42
20
|
dryRun: boolean;
|
|
43
21
|
open?: boolean;
|
|
44
22
|
runId?: string;
|
|
45
|
-
|
|
23
|
+
/** Keys and subject env for the run. Defaults to process.env. Values are scrubbed; names persist. */
|
|
24
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
25
|
+
/** Runs after a clone subject's sandbox exists and before provisioning. */
|
|
26
|
+
prepareDesktop?: NonNullable<RunLabHomes["prepareDesktop"]>;
|
|
27
|
+
/** Test seams: the browser, the session, the E2B module, timers, the renderer and the clock. */
|
|
28
|
+
deps?: LabDeps;
|
|
46
29
|
}
|
|
47
30
|
interface ScriptedBrowserLabSession {
|
|
48
31
|
surface: string;
|
|
@@ -53,9 +36,9 @@ interface ScriptedBrowserLabSession {
|
|
|
53
36
|
}
|
|
54
37
|
export interface ScriptedBrowserLabResult extends AutomaticAnalysisResult {
|
|
55
38
|
schema: typeof SCRIPTED_BROWSER_LAB_SCHEMA;
|
|
56
|
-
/** True when the bundle verified
|
|
57
|
-
* without a harness error). The subject failing the script is successful
|
|
58
|
-
*
|
|
39
|
+
/** True when the bundle verified and (dry-run, or every session reached a terminal verdict
|
|
40
|
+
* without a harness error). The subject failing the script is successful evidence, and the lab
|
|
41
|
+
* does not fail for it. */
|
|
59
42
|
ok: boolean;
|
|
60
43
|
cwd: string;
|
|
61
44
|
labId: string;
|
|
@@ -81,7 +64,7 @@ export interface ScriptedBrowserLabResult extends AutomaticAnalysisResult {
|
|
|
81
64
|
observer?: ObserverResult;
|
|
82
65
|
warnings: string[];
|
|
83
66
|
error?: {
|
|
84
|
-
code: "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "
|
|
67
|
+
code: "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "HUMANISH_LAB_OPTION_UNSUPPORTED" | "HUMANISH_SCRIPTED_LAB_FAILED" | "HUMANISH_SCRIPTED_LAB_ACTOR_UNSUPPORTED" | "HUMANISH_SCRIPTED_LAB_SCENARIO_INVALID" | "HUMANISH_SCRIPTED_LAB_SUBJECT_UNSAFE" | "HUMANISH_SCRIPTED_LAB_BROWSER_MISSING" | "HUMANISH_SCRIPTED_LAB_KEYS_MISSING" | "HUMANISH_SCRIPTED_LAB_SUBJECT_ENV_MISSING" | "HUMANISH_SCRIPTED_LAB_GETHOST_UNAVAILABLE" | "HUMANISH_RUN_ID_IN_USE";
|
|
85
68
|
message: string;
|
|
86
69
|
};
|
|
87
70
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
// The scripted-browser lab's schema constant,
|
|
2
|
-
import { renderObserver } from "../../observer/render.js";
|
|
1
|
+
// The scripted-browser lab's schema constant, options and result types.
|
|
3
2
|
export const SCRIPTED_BROWSER_LAB_SCHEMA = "humanish.scripted-lab-result.v1";
|
|
@@ -5,7 +5,7 @@ import { participantAssignment } from "../../lab/participant-assignment.js";
|
|
|
5
5
|
import { participantEvent, participantRecord, participantStream, } from "../../run/participant-records.js";
|
|
6
6
|
import { declaredScreenForRender } from "../../substrates/e2b/desktop-geometry.js";
|
|
7
7
|
import { publicSafeRouteLabel } from "./provenance.js";
|
|
8
|
-
import { participantTaxonomyLabel } from "./
|
|
8
|
+
import { participantTaxonomyLabel } from "./participant-specs.js";
|
|
9
9
|
function participantView(ctx, spec, index) {
|
|
10
10
|
const { args, external, inProgress } = ctx;
|
|
11
11
|
const taxonomy = participantTaxonomyLabel(spec.planned.labels);
|
|
@@ -31,8 +31,8 @@ function participantView(ctx, spec, index) {
|
|
|
31
31
|
? "Actor desktop is running; the attached Observer hydrates the runtime stream URL without persisting it."
|
|
32
32
|
: "Contract actor only: dry-run produced the evidence shape without launching a desktop or spending provider tokens.");
|
|
33
33
|
const traceScreenshotMode = session?.trace.redaction.screenshots;
|
|
34
|
-
// Include `declared` on the no-outcome fallback too (dry-run, skipped
|
|
35
|
-
//
|
|
34
|
+
// Include `declared` on the no-outcome fallback too (dry-run, skipped participant): otherwise an
|
|
35
|
+
// absent `declared` means either "the preset rendered faithfully" or "there was no live
|
|
36
36
|
// outcome", and a dry-run bundle keeps the self-confirming shape this field exists to kill.
|
|
37
37
|
const fallbackDeclared = declaredScreenForRender(spec.planned.device.preset, spec.planned.device.name, spec.planned.device.resolution);
|
|
38
38
|
const desktopGeometry = outcome?.desktopGeometry ?? {
|
|
@@ -80,8 +80,8 @@ function sharedWorldSimulation(ctx, spec, index, view) {
|
|
|
80
80
|
: inProgress
|
|
81
81
|
? `Persona ${spec.planned.id}${taxonomy} (${spec.persona.id}) is running against the shared plane.`
|
|
82
82
|
: `Contract persona ${spec.planned.id}${taxonomy} (${spec.persona.id}) for ${args.descriptor.id} against the shared plane at ${ctx.appUrl}.`,
|
|
83
|
-
startedAt: args.createdAt,
|
|
84
|
-
updatedAt: args.createdAt,
|
|
83
|
+
startedAt: args.run.createdAt,
|
|
84
|
+
updatedAt: args.run.createdAt,
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
function sharedWorldStream(ctx, spec, index, view) {
|
|
@@ -95,7 +95,7 @@ function sharedWorldStream(ctx, spec, index, view) {
|
|
|
95
95
|
label: `Concurrent persona ${spec.planned.id}${taxonomy} — ${args.plan.labId}`,
|
|
96
96
|
status: view.status,
|
|
97
97
|
transport: "snapshot",
|
|
98
|
-
updatedAt: args.createdAt,
|
|
98
|
+
updatedAt: args.run.createdAt,
|
|
99
99
|
embed: lastScreenshot
|
|
100
100
|
? {
|
|
101
101
|
kind: "screenshot",
|
|
@@ -135,7 +135,7 @@ function sharedWorldStream(ctx, spec, index, view) {
|
|
|
135
135
|
},
|
|
136
136
|
]
|
|
137
137
|
: []),
|
|
138
|
-
// Run-level comms evidence belongs to the
|
|
138
|
+
// Run-level comms evidence belongs to the one shared app, and to no persona: register it once, on
|
|
139
139
|
// the first stream, so the bundle's existence-verify + public-safety scan cover it without
|
|
140
140
|
// double-counting across seats.
|
|
141
141
|
...(index === 0 && args.commsArtifactPath
|
|
@@ -151,7 +151,7 @@ function sharedWorldStream(ctx, spec, index, view) {
|
|
|
151
151
|
}
|
|
152
152
|
function sharedWorldEvents(ctx, spec, view) {
|
|
153
153
|
const { args, inProgress, nextEventId } = ctx;
|
|
154
|
-
const createdAt = args.createdAt;
|
|
154
|
+
const createdAt = args.run.createdAt;
|
|
155
155
|
const { outcome, session } = view;
|
|
156
156
|
const events = [];
|
|
157
157
|
const record = (event) => events.push(participantEvent(spec, event));
|
|
@@ -2,7 +2,7 @@ import { type RunBundle } from "../../run/bundle.js";
|
|
|
2
2
|
import { type SharedWorldJudgment } from "../../run/judge.js";
|
|
3
3
|
import { type ActorRunResult, type ConcurrentBundleArgs } from "./types.js";
|
|
4
4
|
/** Max windows live at the same instant (sweep over start/end points). The honest simultaneity
|
|
5
|
-
* count:
|
|
5
|
+
* count: the participant count says how many existed; this says how many ever ran at once. */
|
|
6
6
|
export declare function maxSimultaneousWindows(windows: Array<{
|
|
7
7
|
startedAt: number;
|
|
8
8
|
endedAt: number;
|
|
@@ -15,6 +15,6 @@ export declare function maxSimultaneousWindows(windows: Array<{
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function judgeSharedWorldRun(args: Omit<ConcurrentBundleArgs, "judgment">): SharedWorldJudgment;
|
|
17
17
|
export declare function actorRunPassed(result: ActorRunResult | undefined): boolean;
|
|
18
|
-
/** Project the concurrent run into a humanish.run-bundle.v1 with the
|
|
18
|
+
/** Project the concurrent run into a humanish.run-bundle.v1 with the concurrent shared-world block. */
|
|
19
19
|
export declare function buildConcurrentSharedWorldBundle(args: ConcurrentBundleArgs): RunBundle;
|
|
20
20
|
export declare function renderConcurrentReviewMarkdown(bundle: RunBundle): string;
|
|
@@ -12,10 +12,10 @@ import { judgeSharedWorld, participantPassed, sharedWorldShortfall, } from "../.
|
|
|
12
12
|
import { combineCheckpointDigest } from "./checkpoints.js";
|
|
13
13
|
import { hostOriginDigest } from "./provenance.js";
|
|
14
14
|
import { participantEvent, participantIds } from "../../run/participant-records.js";
|
|
15
|
-
import { sharedWorldParticipantRecords } from "./
|
|
15
|
+
import { sharedWorldParticipantRecords } from "./bundle-records.js";
|
|
16
16
|
import { CONCURRENT_ATTRIBUTION_LIMITS, EXTERNAL_PUBLIC_ATTRIBUTION_LIMITS, } from "./types.js";
|
|
17
17
|
/** Max windows live at the same instant (sweep over start/end points). The honest simultaneity
|
|
18
|
-
* count:
|
|
18
|
+
* count: the participant count says how many existed; this says how many ever ran at once. */
|
|
19
19
|
export function maxSimultaneousWindows(windows) {
|
|
20
20
|
const points = windows
|
|
21
21
|
.filter((w) => w.endedAt > w.startedAt)
|
|
@@ -90,7 +90,7 @@ function formatSharedWorldActorOutcomes(outcomes, expectedCount) {
|
|
|
90
90
|
}
|
|
91
91
|
/** The run's first two events: its creation and the shared plane's provenance. */
|
|
92
92
|
function planeEvents(args, external) {
|
|
93
|
-
const { plan, descriptor, createdAt, dryRun, actorSpecs } = args;
|
|
93
|
+
const { plan, descriptor, run: { createdAt }, dryRun, actorSpecs, } = args;
|
|
94
94
|
const events = [];
|
|
95
95
|
events.push({
|
|
96
96
|
id: "event-000-created",
|
|
@@ -108,8 +108,8 @@ function planeEvents(args, external) {
|
|
|
108
108
|
? `packed working tree (archiveSha256 ${args.subject.archiveSha256}${args.subject.dirty === true ? ", dirty working tree" : args.subject.dirty === false ? ", clean working tree" : ""})`
|
|
109
109
|
: "packed working tree (archive digest unresolved; provisioning failed before resolution)"
|
|
110
110
|
: `clone of ${args.subject.repo}${args.subjectCommit ? `@${args.subjectCommit}` : ""}`;
|
|
111
|
-
// External-public plane provenance
|
|
112
|
-
//
|
|
111
|
+
// External-public plane provenance differs: an operator-declared, operator-owned public
|
|
112
|
+
// deployment humanish neither provisioned nor seeded, with no getHost, no clone and no synthetic
|
|
113
113
|
// attestation (claiming synthetic on a real site is a lie). The origin persists digest-only.
|
|
114
114
|
// planSharedWorldLab refuses an external-public plane without a declared owner; the fallback
|
|
115
115
|
// says so rather than naming one.
|
|
@@ -130,7 +130,7 @@ function planeEvents(args, external) {
|
|
|
130
130
|
/** The sharedWorld block: seat windows, the state series, seat outcomes and the plane. */
|
|
131
131
|
function sharedWorldEvidence(args, external, inProgress, planeCommit) {
|
|
132
132
|
const { plan, dryRun, actorSpecs, actorResults } = args;
|
|
133
|
-
// Build the concurrent shared-world evidence block. routeHostDigest is sha256-16 of the
|
|
133
|
+
// Build the concurrent shared-world evidence block. routeHostDigest is sha256-16 of the origin each
|
|
134
134
|
// seat reached: on getHost the seat URL the actor drove (verify confirms == plane.hostDigest); on
|
|
135
135
|
// external-public the seat's CDP-OBSERVED URL origin (verify confirms == plane.publicOriginDigest).
|
|
136
136
|
const fallbackHostDigest = external
|
|
@@ -156,7 +156,7 @@ function sharedWorldEvidence(args, external, inProgress, planeCommit) {
|
|
|
156
156
|
seedDigest: args.seedDigest,
|
|
157
157
|
};
|
|
158
158
|
});
|
|
159
|
-
// Option A (external-public):
|
|
159
|
+
// Option A (external-public): no authoritative shared-state proof, so stateSeries is omitted (there
|
|
160
160
|
// is no in-sandbox filesystem to digest; concurrency is proven by temporal co-occupancy + lobby
|
|
161
161
|
// convergence). The provisioned-getHost plane keeps its authoritative in-sandbox checkpoint series.
|
|
162
162
|
const stateSeries = external
|
|
@@ -182,13 +182,13 @@ function sharedWorldEvidence(args, external, inProgress, planeCommit) {
|
|
|
182
182
|
};
|
|
183
183
|
});
|
|
184
184
|
// The plane block is plane-class-specific. getHost: harness-minted hostDigest + synthetic
|
|
185
|
-
// attestation. external-public: operator-declared publicOriginDigest,
|
|
186
|
-
// (claiming synthetic on a real site would be
|
|
185
|
+
// attestation. external-public: operator-declared publicOriginDigest, no hostDigest, no exposure
|
|
186
|
+
// (claiming synthetic on a real site would be false; verify asserts both are absent there).
|
|
187
187
|
const plane = external
|
|
188
188
|
? {
|
|
189
189
|
seedDigest: args.seedDigest,
|
|
190
190
|
envNames: [],
|
|
191
|
-
// publicOriginDigest is the
|
|
191
|
+
// publicOriginDigest is the observed convergence origin; declaredOriginDigest records the
|
|
192
192
|
// operator-declared origin for reference (a redirect makes them differ — not a failure).
|
|
193
193
|
...(args.publicOriginDigest === undefined
|
|
194
194
|
? {}
|
|
@@ -216,7 +216,7 @@ function sharedWorldEvidence(args, external, inProgress, planeCommit) {
|
|
|
216
216
|
? [...EXTERNAL_PUBLIC_ATTRIBUTION_LIMITS]
|
|
217
217
|
: [...CONCURRENT_ATTRIBUTION_LIMITS],
|
|
218
218
|
laneWindows: windows,
|
|
219
|
-
// Option A: external-public carries
|
|
219
|
+
// Option A: external-public carries no stateSeries.
|
|
220
220
|
...(stateSeries === undefined ? {} : { stateSeries }),
|
|
221
221
|
outcomes,
|
|
222
222
|
...(args.lobbyConvergenceDigest === undefined
|
|
@@ -241,7 +241,7 @@ function finishedGaps(actorResults, shortfall) {
|
|
|
241
241
|
}
|
|
242
242
|
/** Records the concurrency event and returns the review. */
|
|
243
243
|
function concurrencyReview(args, external, inProgress, evidence, events, nextEventId) {
|
|
244
|
-
const { plan, descriptor, createdAt, dryRun, actorSpecs, actorResults } = args;
|
|
244
|
+
const { plan, descriptor, run: { createdAt }, dryRun, actorSpecs, actorResults, } = args;
|
|
245
245
|
const { sharedWorld, windows, stateSeries, outcomes } = evidence;
|
|
246
246
|
const overlaps = args.judgment.world.overlap;
|
|
247
247
|
const deltas = (stateSeries ?? []).filter((snapshot, i) => i > 0 && snapshot.digest !== (stateSeries ?? [])[i - 1].digest).length;
|
|
@@ -251,8 +251,8 @@ function concurrencyReview(args, external, inProgress, evidence, events, nextEve
|
|
|
251
251
|
const convergenceLabel = external
|
|
252
252
|
? `; lobby convergence ${args.lobbyConvergenceDigest ? "PROVEN (all participants reached one /lobby/CODE)" : "not observed"}`
|
|
253
253
|
: "";
|
|
254
|
-
// The count that matters is how many
|
|
255
|
-
// 6-
|
|
254
|
+
// The count that matters is how many participants were live at once, which can be fewer than exist:
|
|
255
|
+
// a 6-participant run capped at 3 must never read as 6-wide concurrency (#350, the field failure).
|
|
256
256
|
const capForReport = plan.concurrency;
|
|
257
257
|
const maxLive = maxSimultaneousWindows(windows);
|
|
258
258
|
events.push({
|
|
@@ -262,7 +262,7 @@ function concurrencyReview(args, external, inProgress, evidence, events, nextEve
|
|
|
262
262
|
type: "concurrent-shared-world.concurrency",
|
|
263
263
|
message: `Concurrency: ${windows.length} participant(s)${dryRun ? " (dry-run contract; $0)" : `, up to ${maxLive} live at once (cap ${capForReport}), overlap ${overlaps ? "PROVEN" : "not observed"}`}; ${stateSeriesLabel}${convergenceLabel}. Attribution ceiling: ${sharedWorld.attributionLimits.join(", ")}. ${dryRun ? "This contract-only run proves no live concurrency, scale, or adoption." : "This run reports only its own observed overlap and state changes; it does not prove scale, repeatability, or adopter-harness replacement."}`,
|
|
264
264
|
});
|
|
265
|
-
// The judge's verdict (judgeSharedWorld): every seat produced a terminal, engaged
|
|
265
|
+
// The judge's verdict (judgeSharedWorld): every seat produced a terminal, engaged, passed session.
|
|
266
266
|
// Mission endpoint and completion reasons are reported separately below; `outcomes[].ok` is not
|
|
267
267
|
// renamed into mission success (#364).
|
|
268
268
|
const verdict = args.judgment.verdict;
|
|
@@ -270,7 +270,7 @@ function concurrencyReview(args, external, inProgress, evidence, events, nextEve
|
|
|
270
270
|
const review = {
|
|
271
271
|
schema: REVIEW_SCHEMA,
|
|
272
272
|
verdict,
|
|
273
|
-
// Plane-class-aware: the external-public plane has
|
|
273
|
+
// Plane-class-aware: the external-public plane has no getHost/clone/seed and carries no
|
|
274
274
|
// authoritative state series, so its summary must not claim a getHost-exposed plane (dry-run) nor
|
|
275
275
|
// report "state delta(s) under load" (live) — it reports lobby convergence instead.
|
|
276
276
|
summary: dryRun
|
|
@@ -294,15 +294,15 @@ function concurrencyReview(args, external, inProgress, evidence, events, nextEve
|
|
|
294
294
|
};
|
|
295
295
|
return review;
|
|
296
296
|
}
|
|
297
|
-
/** Project the concurrent run into a humanish.run-bundle.v1 with the
|
|
297
|
+
/** Project the concurrent run into a humanish.run-bundle.v1 with the concurrent shared-world block. */
|
|
298
298
|
export function buildConcurrentSharedWorldBundle(args) {
|
|
299
|
-
const { plan, descriptor, createdAt, dryRun, actorSpecs, actorResults } = args;
|
|
299
|
+
const { plan, descriptor, run: { createdAt }, dryRun, actorSpecs, actorResults, } = args;
|
|
300
300
|
const inProgress = args.inProgress === true;
|
|
301
301
|
const external = (args.planeClass ?? "provisioned-getHost") === "external-public";
|
|
302
302
|
const simulations = [];
|
|
303
303
|
const streams = [];
|
|
304
304
|
// Public-safe label only — neither the raw getHost URL (provisioned) nor the raw public origin
|
|
305
|
-
// (external-public) lands in the bundle. The plane identity is a
|
|
305
|
+
// (external-public) lands in the bundle. The plane identity is a digest (plane.hostDigest on
|
|
306
306
|
// getHost; plane.publicOriginDigest on external-public).
|
|
307
307
|
const appUrl = external ? "[external-public-plane]" : "[provisioned-subject]";
|
|
308
308
|
const planeCommit = external ? undefined : dryRun ? undefined : args.subjectCommit;
|
|
@@ -323,13 +323,9 @@ export function buildConcurrentSharedWorldBundle(args) {
|
|
|
323
323
|
const ranLive = actorResults.some((result) => result.outcome.session !== undefined || result.outcome.sessionError !== undefined);
|
|
324
324
|
const cost = concurrentCostSummary(args, inProgress);
|
|
325
325
|
return {
|
|
326
|
-
...bundleHead({
|
|
326
|
+
...bundleHead(args.run, {
|
|
327
327
|
...receivingPublication(plan.residual, args.dryRun),
|
|
328
|
-
runId: args.runId,
|
|
329
|
-
mode: dryRun ? "dry-run" : "live",
|
|
330
328
|
participants: actorSpecs.length,
|
|
331
|
-
createdAt,
|
|
332
|
-
...(args.lab === undefined ? {} : { lab: args.lab }),
|
|
333
329
|
source: args.source,
|
|
334
330
|
}),
|
|
335
331
|
persona: {
|
|
@@ -381,7 +377,7 @@ export function buildConcurrentSharedWorldBundle(args) {
|
|
|
381
377
|
};
|
|
382
378
|
}
|
|
383
379
|
/**
|
|
384
|
-
* Priced like per-lane
|
|
380
|
+
* Priced like `per-lane-worlds`: each participant's model tokens and desktop, plus the provisioned plane's
|
|
385
381
|
* desktop. Absent when nothing ran, so dry runs and in-progress snapshots stay byte-stable.
|
|
386
382
|
*/
|
|
387
383
|
function concurrentCostSummary(args, inProgress) {
|
|
@@ -416,7 +412,7 @@ function concurrentCostSummary(args, inProgress) {
|
|
|
416
412
|
],
|
|
417
413
|
});
|
|
418
414
|
}
|
|
419
|
-
/** The declared (dry-run) state digest: the probe
|
|
415
|
+
/** The declared (dry-run) state digest: the probe recipe (command digests), no run. */
|
|
420
416
|
function declaredStateDigest(state) {
|
|
421
417
|
const probes = state?.checkpoint ?? [];
|
|
422
418
|
return combineCheckpointDigest(probes.map((probe) => `${probe.name}=${commandDigestOf(probe.command)}`));
|
|
@@ -2,12 +2,12 @@ import type { Shell } from "../../substrates/shell.js";
|
|
|
2
2
|
import { type DetachedTimers } from "../../substrates/detached.js";
|
|
3
3
|
import { type LabSubjectState, type LabSubjectStateCheckpoint } from "../../lab/types.js";
|
|
4
4
|
import { type SharedWorldCheckpoint } from "../../run/shared-world-evidence.js";
|
|
5
|
-
/** Combine a snapshot's per-probe digests into
|
|
5
|
+
/** Combine a snapshot's per-probe digests into one sha256-16 (digest-only; no raw value). */
|
|
6
6
|
export declare function combineCheckpointDigest(parts: string[]): string;
|
|
7
7
|
/**
|
|
8
|
-
* Run
|
|
8
|
+
* Run one checkpoint snapshot live: each declared probe runs read-only via the detached
|
|
9
9
|
* primitive; its stdout is literal-scrubbed (provisioned values + the probe's declared redact
|
|
10
|
-
* literals, folded into `scrub`) then pattern-redacted, then digested. Only the
|
|
10
|
+
* literals, folded into `scrub`) then pattern-redacted, then digested. Only the combined digest
|
|
11
11
|
* persists — never the raw value (the seed-step lockdown). Unique step names per snapshot prevent
|
|
12
12
|
* stale-status reuse across snapshots.
|
|
13
13
|
*/
|
|
@@ -21,5 +21,5 @@ export declare function runCheckpointSnapshot(args: {
|
|
|
21
21
|
requestTimeoutMs: number;
|
|
22
22
|
timers: DetachedTimers;
|
|
23
23
|
}): Promise<SharedWorldCheckpoint>;
|
|
24
|
-
/** sha256-16 over the ordered seed-step command digests
|
|
24
|
+
/** sha256-16 over the ordered seed-step command digests: the seeded-state recipe identity. */
|
|
25
25
|
export declare function seedRecipeDigest(state: LabSubjectState | undefined): string;
|
|
@@ -6,14 +6,14 @@ import { redactText } from "../../evidence/redaction.js";
|
|
|
6
6
|
import {} from "../../run/shared-world-evidence.js";
|
|
7
7
|
// Per-checkpoint probe budget (read-only aggregate probes are fast).
|
|
8
8
|
const CHECKPOINT_TIMEOUT_MS = 60_000;
|
|
9
|
-
/** Combine a snapshot's per-probe digests into
|
|
9
|
+
/** Combine a snapshot's per-probe digests into one sha256-16 (digest-only; no raw value). */
|
|
10
10
|
export function combineCheckpointDigest(parts) {
|
|
11
11
|
return commandDigestOf(parts.join("\n"));
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Run
|
|
14
|
+
* Run one checkpoint snapshot live: each declared probe runs read-only via the detached
|
|
15
15
|
* primitive; its stdout is literal-scrubbed (provisioned values + the probe's declared redact
|
|
16
|
-
* literals, folded into `scrub`) then pattern-redacted, then digested. Only the
|
|
16
|
+
* literals, folded into `scrub`) then pattern-redacted, then digested. Only the combined digest
|
|
17
17
|
* persists — never the raw value (the seed-step lockdown). Unique step names per snapshot prevent
|
|
18
18
|
* stale-status reuse across snapshots.
|
|
19
19
|
*/
|
|
@@ -39,7 +39,7 @@ export async function runCheckpointSnapshot(args) {
|
|
|
39
39
|
deltaFromPrev: args.prevDigest !== undefined && digest !== args.prevDigest,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
/** sha256-16 over the ordered seed-step command digests
|
|
42
|
+
/** sha256-16 over the ordered seed-step command digests: the seeded-state recipe identity. */
|
|
43
43
|
export function seedRecipeDigest(state) {
|
|
44
44
|
const seed = state?.seed ?? [];
|
|
45
45
|
return commandDigestOf(seed.map((step) => `${step.name}:${commandDigestOf(step.command)}`).join("\n"));
|
|
@@ -14,24 +14,25 @@ export interface SubjectComms {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function subjectCommsOf(config: Pick<LabConfig, "comms">, planeClass: ConcurrentSharedWorldPlaneClass): SubjectComms;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* it cannot host a catch
|
|
17
|
+
* Adopter-hosted ingress (#328): on the external-public plane the harness provisions nothing, so
|
|
18
|
+
* it cannot host a catch. The operator can, and then humanish still does every other part of
|
|
19
19
|
* the funnel: it tells each persona its address and inbox URL, drains the declared catch over
|
|
20
20
|
* HTTP at teardown, and writes the same digest-only evidence. Declaring `external` is what turns
|
|
21
21
|
* the previously-inert block into a working one. Returns an error message when the declared catch
|
|
22
22
|
* does not answer as a humanish catch.
|
|
23
23
|
*/
|
|
24
|
-
export declare function prepareExternalComms(config: Pick<LabConfig, "comms">, planeClass: ConcurrentSharedWorldPlaneClass, dryRun: boolean, warnings: string[]): Promise<{
|
|
24
|
+
export declare function prepareExternalComms(config: Pick<LabConfig, "comms">, planeClass: ConcurrentSharedWorldPlaneClass, dryRun: boolean, warnings: string[], env: Record<string, string | undefined>): Promise<{
|
|
25
25
|
ok: true;
|
|
26
26
|
wiring: ExternalCommsWiring | undefined;
|
|
27
27
|
} | {
|
|
28
28
|
ok: false;
|
|
29
|
+
code: "HUMANISH_CONCURRENT_SHARED_WORLD_LAB_COMMS_TOKEN_INVALID" | "HUMANISH_CONCURRENT_SHARED_WORLD_LAB_COMMS_CATCH_UNREACHABLE";
|
|
29
30
|
message: string;
|
|
30
31
|
}>;
|
|
31
32
|
/**
|
|
32
33
|
* Off-app comms evidence (#297): drain everything the in-sandbox catch captured, route it into a
|
|
33
34
|
* host fake inbox addressed to the declared recipients, and write the run-level digest-only thread
|
|
34
|
-
* artifact
|
|
35
|
+
* artifact while the subject is still alive, before it is killed. Wrapped so a drain error
|
|
35
36
|
* never blocks teardown (invariant: all sandboxes torn down by id in the plane's finally). Returns
|
|
36
37
|
* the thread's path when one was written.
|
|
37
38
|
*/
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
// Off-app comms for the concurrent shared-world route: which email catch a plane gets (in the
|
|
2
2
|
// subject sandbox, or adopter-hosted), and the drains that match captured mail to the seats'
|
|
3
3
|
// declared inboxes and write the digest-only thread.
|
|
4
|
+
import { catchTokenOf, catchTokenRefusal, collectExternalCommsEvidence, } from "../../comms/external-evidence.js";
|
|
4
5
|
import { FakeInbox } from "../../comms/fake-inbox.js";
|
|
5
6
|
import { prepareReceivingRun } from "../../comms/receiving-runtime.js";
|
|
6
|
-
import { DEFAULT_SANDBOX_CATCH_PORT, collectCommsThread,
|
|
7
|
+
import { DEFAULT_SANDBOX_CATCH_PORT, collectCommsThread, externalCatchHealthy, externalInboxUrl, } from "../../comms/sandbox-catch.js";
|
|
7
8
|
import { redactText, toErrorMessage } from "../../evidence/redaction.js";
|
|
8
9
|
import { writeContainedOutputFile } from "../../run/contained-output.js";
|
|
9
10
|
import { addressedRecipients } from "../../lab/parse/comms.js";
|
|
10
|
-
// Off-app comms (#297): on the provisioned-getHost plane the harness owns the
|
|
11
|
-
// it can redirect the app's email-API sends into an in-sandbox catch and evidence them. Gated
|
|
11
|
+
// Off-app comms (#297): on the provisioned-getHost plane the harness owns the one subject sandbox, so
|
|
12
|
+
// it can redirect the app's email-API sends into an in-sandbox catch and evidence them. Gated entirely
|
|
12
13
|
// on config.comms — no comms declared → zero change. The base-URL env is injected into the subject
|
|
13
14
|
// sandbox at create (fixed port known up front); the catch is deployed before serve; the drain + digest
|
|
14
|
-
// evidence run at subject teardown, then register run-level in the bundle.
|
|
15
|
+
// evidence run at subject teardown, then register run-level in the bundle. Unavailable on the
|
|
15
16
|
// external-public plane (the app is an operator-owned deployment the harness never provisions).
|
|
16
17
|
export function subjectCommsOf(config, planeClass) {
|
|
17
18
|
const commsEmail = planeClass === "provisioned-getHost" && config.comms?.email?.kind === "fake"
|
|
@@ -26,14 +27,14 @@ export function subjectCommsOf(config, planeClass) {
|
|
|
26
27
|
return { email: commsEmail, port: commsPort, env: commsEnv };
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
-
* it cannot host a catch
|
|
30
|
+
* Adopter-hosted ingress (#328): on the external-public plane the harness provisions nothing, so
|
|
31
|
+
* it cannot host a catch. The operator can, and then humanish still does every other part of
|
|
31
32
|
* the funnel: it tells each persona its address and inbox URL, drains the declared catch over
|
|
32
33
|
* HTTP at teardown, and writes the same digest-only evidence. Declaring `external` is what turns
|
|
33
34
|
* the previously-inert block into a working one. Returns an error message when the declared catch
|
|
34
35
|
* does not answer as a humanish catch.
|
|
35
36
|
*/
|
|
36
|
-
export async function prepareExternalComms(config, planeClass, dryRun, warnings) {
|
|
37
|
+
export async function prepareExternalComms(config, planeClass, dryRun, warnings, env) {
|
|
37
38
|
const externalComms = planeClass === "external-public" ? config.comms?.email?.external : undefined;
|
|
38
39
|
const externalCommsEmail = externalComms ? config.comms?.email : undefined;
|
|
39
40
|
if (config.comms?.email?.kind === "fake" &&
|
|
@@ -44,12 +45,20 @@ export async function prepareExternalComms(config, planeClass, dryRun, warnings)
|
|
|
44
45
|
if (!externalComms || !externalCommsEmail)
|
|
45
46
|
return { ok: true, wiring: undefined };
|
|
46
47
|
const inboxUrl = externalInboxUrl(externalComms);
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
const tokenRefusal = catchTokenRefusal(catchTokenOf(externalComms, env));
|
|
49
|
+
if (tokenRefusal !== undefined)
|
|
50
|
+
return {
|
|
51
|
+
ok: false,
|
|
52
|
+
code: "HUMANISH_CONCURRENT_SHARED_WORLD_LAB_COMMS_TOKEN_INVALID",
|
|
53
|
+
message: tokenRefusal,
|
|
54
|
+
};
|
|
55
|
+
// Fail closed before any actor sandbox is created: a comms lab whose catch is unreachable
|
|
56
|
+
// collects nothing while every participant still spends. The probe asserts our service marker in
|
|
49
57
|
// /health, so an adopter's proxy answering 200 for everything cannot pass for a catch.
|
|
50
58
|
if (!dryRun && !(await externalCatchHealthy(externalComms))) {
|
|
51
59
|
return {
|
|
52
60
|
ok: false,
|
|
61
|
+
code: "HUMANISH_CONCURRENT_SHARED_WORLD_LAB_COMMS_CATCH_UNREACHABLE",
|
|
53
62
|
message: `The external comms catch or inbox is unreachable or incompatible (GET /health must identify humanish-comms-catch and advertise recipient-inbox-v1). Update humanish on the catch host and restart it with \`humanish comms catch\` on that host, or drop comms.email to run without the inbox funnel.`,
|
|
54
63
|
};
|
|
55
64
|
}
|
|
@@ -58,7 +67,7 @@ export async function prepareExternalComms(config, planeClass, dryRun, warnings)
|
|
|
58
67
|
/**
|
|
59
68
|
* Off-app comms evidence (#297): drain everything the in-sandbox catch captured, route it into a
|
|
60
69
|
* host fake inbox addressed to the declared recipients, and write the run-level digest-only thread
|
|
61
|
-
* artifact
|
|
70
|
+
* artifact while the subject is still alive, before it is killed. Wrapped so a drain error
|
|
62
71
|
* never blocks teardown (invariant: all sandboxes torn down by id in the plane's finally). Returns
|
|
63
72
|
* the thread's path when one was written.
|
|
64
73
|
*/
|
|
@@ -101,37 +110,15 @@ export async function drainSubjectComms(ctx, commsEmail, subjectShell, deployedC
|
|
|
101
110
|
* masks the run's own outcome. Returns the thread's path when one was written.
|
|
102
111
|
*/
|
|
103
112
|
export async function drainExternalComms(ctx, comms) {
|
|
104
|
-
const {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const authToken = externalComms.authTokenEnv === undefined ? undefined : env[externalComms.authTokenEnv];
|
|
114
|
-
const collected = await collectExternalCommsThread({
|
|
115
|
-
external: { ...externalComms, ...(authToken === undefined ? {} : { authToken }) },
|
|
116
|
-
channel: commsChannel,
|
|
117
|
-
inboxes: commsInboxes,
|
|
118
|
-
});
|
|
119
|
-
if (collected.artifact) {
|
|
120
|
-
const path = "comms/thread.json";
|
|
121
|
-
await writeContainedOutputFile(runPaths, path, `${JSON.stringify(collected.artifact, null, 2)}\n`, "utf8");
|
|
122
|
-
return path;
|
|
123
|
-
}
|
|
124
|
-
else if (collected.captured > 0) {
|
|
125
|
-
warnings.push(`Comms catch captured ${collected.captured} email send(s) but none matched a declared recipient inbox — no comms evidence written. Declare comms.email.recipients[].address to match the address the app sends to.`);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
warnings.push(`Comms catch captured ZERO email sends — your app never delivered mail through the catch at ${externalComms.catchBaseUrl}. Verify the app's email-API base URL points at it and that the flow reached an email step.`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
warnings.push(`Comms evidence collection failed against the adopter-hosted catch (run continues): ${redactText(toErrorMessage(error))}`);
|
|
133
|
-
}
|
|
134
|
-
return undefined;
|
|
113
|
+
const { path, warnings } = await collectExternalCommsEvidence({
|
|
114
|
+
external: comms.external,
|
|
115
|
+
email: comms.email,
|
|
116
|
+
env: ctx.env,
|
|
117
|
+
runPaths: ctx.runPaths,
|
|
118
|
+
knownSecretValues: ctx.knownSecretValues,
|
|
119
|
+
});
|
|
120
|
+
ctx.warnings.push(...warnings);
|
|
121
|
+
return path;
|
|
135
122
|
}
|
|
136
123
|
/** What receiving guards: the lab's email declaration and the subject env names and values. */
|
|
137
124
|
export function receivingSourceOf(residual, env) {
|
|
@@ -11,11 +11,11 @@ export interface ExternalPublicPlaneOutcome {
|
|
|
11
11
|
commsArtifactPath: string | undefined;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* The operator-
|
|
15
|
-
* operator-
|
|
16
|
-
* appUrl
|
|
17
|
-
* lobby-trivia.example.test 307-redirects) makes the seats'
|
|
18
|
-
* is expected and
|
|
14
|
+
* The operator-declared origin (from subject.appUrl), recorded for evidence and reference only. The
|
|
15
|
+
* operator-ownership claim rests on the subject.publicTarget.authorized attestation + this declared
|
|
16
|
+
* appUrl; digest equality plays no part (blocker 2): a normal cross-origin redirect (apex->www, http->https;
|
|
17
|
+
* lobby-trivia.example.test 307-redirects) makes the seats' observed origin differ from the declared one, which
|
|
18
|
+
* is expected and must not fail the run. Persisted digest-only (never the raw origin).
|
|
19
19
|
*/
|
|
20
20
|
export declare function declaredOriginDigestOf(publicAppUrl: string): string | undefined;
|
|
21
21
|
export declare function runExternalPublicPlane(ctx: PlaneContext, live: LiveParticipants, inbox: ExternalCommsWiring | undefined): Promise<ExternalPublicPlaneOutcome>;
|