humanish 0.106.0 → 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 -2
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +24 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -6
- 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 +31 -4
- package/dist/actors/codex/qualified-versions.js +51 -6
- 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 +10 -8
- package/dist/actors/contract.js +7 -1
- 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.d.ts +2 -0
- package/dist/lab/composition-rules.js +35 -26
- 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 +6 -2
- package/dist/lab/plan-base.js +22 -7
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +33 -7
- 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/observer-app.html +1 -1
- 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} +14 -13
- 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 +58 -33
- 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 +59 -65
- package/dist/routes/computer-use/preflight.d.ts +6 -11
- package/dist/routes/computer-use/preflight.js +26 -18
- 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 -17
- package/dist/routes/computer-use/setup.js +98 -86
- 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 -211
- package/dist/routes/computer-use/types.js +13 -6
- 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 +11 -6
- 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} +46 -51
- 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 +48 -41
- 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 +4 -2
- package/dist/routes/terminal/live-sandbox.js +25 -21
- 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 +5 -3
- package/dist/routes/terminal/sandbox.js +13 -16
- 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 +7 -1
- package/dist/run/reclaim.js +24 -4
- 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/desktop-session.d.ts +2 -0
- 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.d.ts +2 -0
- package/dist/substrates/e2b/sandbox.js +22 -8
- package/dist/substrates/e2b/sdk.d.ts +12 -1
- package/dist/substrates/e2b/sdk.js +30 -9
- 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 +40 -4
- 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,14 +1,51 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { isRunAdapterScore } from "../run/bundle-shape.js";
|
|
3
|
+
import { isRunFeedbackCandidate } from "../run/feedback-shape.js";
|
|
4
|
+
import { isRecord } from "../run/type-guards.js";
|
|
5
|
+
const OLDER_BACKEND = {
|
|
6
|
+
"computer-use": "cua",
|
|
7
|
+
"shared-world": "concurrent-shared-world",
|
|
8
|
+
};
|
|
9
|
+
const warnedFields = new Set();
|
|
10
|
+
function warnOlderField(name, replacement) {
|
|
11
|
+
if (warnedFields.has(name))
|
|
12
|
+
return;
|
|
13
|
+
warnedFields.add(name);
|
|
14
|
+
process.emitWarning(`BrowserLabScoringContext.${name} is deprecated and is removed in the next minor. Use ${replacement}.`, { type: "DeprecationWarning", code: "HUMANISH_SCORING_CONTEXT_FIELD_DEPRECATED" });
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The scorer's context: the facts, plus the older `backend` and `laneCount` as getters that warn
|
|
18
|
+
* once when a scorer reads them. They are not enumerable, so a spread, `Object.assign`,
|
|
19
|
+
* `JSON.stringify` or `structuredClone` of the context skips them and warns about no field the
|
|
20
|
+
* code never named. `"backend" in ctx` still finds them. Core never reads them.
|
|
21
|
+
*/
|
|
22
|
+
function scorerContext(facts) {
|
|
23
|
+
return Object.defineProperties({ ...facts }, {
|
|
24
|
+
backend: {
|
|
25
|
+
enumerable: false,
|
|
26
|
+
get: () => {
|
|
27
|
+
warnOlderField("backend", "route");
|
|
28
|
+
return OLDER_BACKEND[facts.route];
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
laneCount: {
|
|
32
|
+
enumerable: false,
|
|
33
|
+
get: () => {
|
|
34
|
+
warnOlderField("laneCount", "participantCount");
|
|
35
|
+
return facts.participantCount;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
3
40
|
/** A DECLARED scorer that returned a malformed value never rendered a verdict. */
|
|
4
41
|
export const DECLARED_SCORER_MALFORMED = "Declared product scorer returned a malformed value instead of a verdict; a declared gate that cannot render a pass is recorded as a fail, never a silent pass.";
|
|
5
42
|
/** A DECLARED scorer that threw never rendered a verdict. `detail` is already sanitized. */
|
|
6
43
|
export function declaredScorerThrew(detail) {
|
|
7
44
|
return `Declared product scorer threw before returning a verdict (${detail}); a crashed declared gate is recorded as a fail, never a silent pass.`;
|
|
8
45
|
}
|
|
9
|
-
export async function
|
|
10
|
-
const {
|
|
11
|
-
if (!
|
|
46
|
+
export async function applyBrowserScorer(args) {
|
|
47
|
+
const { scorer, context, bundle, sanitize, warnings, scorerProvenance } = args;
|
|
48
|
+
if (!scorer?.score && !scorer?.deriveFeedback && !scorer?.deriveArtifacts)
|
|
12
49
|
return { failures: [] };
|
|
13
50
|
const declared = scorerProvenance !== undefined;
|
|
14
51
|
// Record the loaded scorer's identity regardless of hook outcome (a throwing/invalid scorer was
|
|
@@ -19,78 +56,86 @@ export async function applyBrowserAdapterHooks(args) {
|
|
|
19
56
|
// The scorer sees a READ-ONLY view of the bundle: it cannot mutate noSpend/cost/review in place to
|
|
20
57
|
// launder a verdict (a tamper attempt throws in the scorer's strict-mode ESM and is caught below as
|
|
21
58
|
// a hook failure). The seam still stamps the REAL bundle.
|
|
22
|
-
const scoringContext = {
|
|
59
|
+
const scoringContext = scorerContext({
|
|
23
60
|
...context,
|
|
24
61
|
bundle: frozenBundleView(context.bundle),
|
|
25
|
-
};
|
|
62
|
+
});
|
|
26
63
|
const scrubValue = (value) => {
|
|
27
64
|
const encoded = JSON.stringify(value);
|
|
28
65
|
return encoded === undefined ? value : JSON.parse(sanitize(encoded));
|
|
29
66
|
};
|
|
30
67
|
const failures = [];
|
|
31
|
-
if (
|
|
68
|
+
if (scorer?.score) {
|
|
32
69
|
try {
|
|
33
|
-
const score = await
|
|
70
|
+
const score = await scorer.score(scoringContext);
|
|
34
71
|
const cleaned = scrubValue(score);
|
|
35
|
-
if (
|
|
72
|
+
if (isRunAdapterScore(cleaned)) {
|
|
36
73
|
bundle.adapterScore = cleaned;
|
|
37
74
|
const message = adapterScoreFailureMessage(bundle);
|
|
38
75
|
if (message !== undefined)
|
|
39
76
|
failures.push(message);
|
|
40
77
|
}
|
|
41
78
|
else {
|
|
42
|
-
warnings.push(
|
|
79
|
+
warnings.push(`scorer.score returned a value that is not a well-formed humanish.adapter-score.v1 (non-empty namespace + status + numeric score + summary); dropped so the bundle stays verifiable.`);
|
|
43
80
|
if (declared)
|
|
44
81
|
failures.push(DECLARED_SCORER_MALFORMED);
|
|
45
82
|
}
|
|
46
83
|
}
|
|
47
84
|
catch (error) {
|
|
48
85
|
const detail = sanitize(error instanceof Error ? error.message : String(error));
|
|
49
|
-
warnings.push(
|
|
86
|
+
warnings.push(`scorer.score threw (${detail}); dropped so the bundle stays verifiable.`);
|
|
50
87
|
if (declared)
|
|
51
88
|
failures.push(declaredScorerThrew(detail));
|
|
52
89
|
}
|
|
53
90
|
}
|
|
54
|
-
if (
|
|
91
|
+
if (scorer?.deriveFeedback) {
|
|
55
92
|
try {
|
|
56
|
-
const candidates = await
|
|
93
|
+
const candidates = await scorer.deriveFeedback(scoringContext);
|
|
57
94
|
const accepted = [];
|
|
58
95
|
for (const candidate of Array.isArray(candidates) ? candidates : []) {
|
|
59
96
|
const cleaned = scrubValue(candidate);
|
|
60
|
-
if (
|
|
97
|
+
if (isAdapterFeedbackCandidate(cleaned))
|
|
61
98
|
accepted.push(cleaned);
|
|
62
99
|
else
|
|
63
|
-
warnings.push(
|
|
100
|
+
warnings.push(`scorer.deriveFeedback returned a candidate that is not a well-formed humanish.feedback-candidate.v1 (or its adapter block lacked a non-empty namespace + data record); dropped so the bundle stays verifiable.`);
|
|
64
101
|
}
|
|
65
102
|
if (accepted.length > 0) {
|
|
66
103
|
bundle.feedbackCandidates = [...bundle.feedbackCandidates, ...accepted];
|
|
67
104
|
}
|
|
68
105
|
}
|
|
69
106
|
catch (error) {
|
|
70
|
-
warnings.push(
|
|
107
|
+
warnings.push(`scorer.deriveFeedback threw (${sanitize(error instanceof Error ? error.message : String(error))}); dropped so the bundle stays verifiable.`);
|
|
71
108
|
}
|
|
72
109
|
}
|
|
73
|
-
if (
|
|
110
|
+
if (scorer?.deriveArtifacts) {
|
|
74
111
|
try {
|
|
75
|
-
const artifacts = await
|
|
112
|
+
const artifacts = await scorer.deriveArtifacts(scoringContext);
|
|
76
113
|
const accepted = [];
|
|
77
114
|
for (const artifact of Array.isArray(artifacts) ? artifacts : []) {
|
|
78
115
|
const cleaned = scrubValue(artifact);
|
|
79
116
|
if (isAdapterArtifactShape(cleaned))
|
|
80
117
|
accepted.push(cleaned);
|
|
81
118
|
else
|
|
82
|
-
warnings.push(
|
|
119
|
+
warnings.push(`scorer.deriveArtifacts returned an artifact that is not a well-formed humanish.adapter-artifact.v1 (non-empty namespace + label + local path + supported kind); dropped so the bundle stays verifiable.`);
|
|
83
120
|
}
|
|
84
121
|
if (accepted.length > 0) {
|
|
85
122
|
bundle.adapterArtifacts = [...(bundle.adapterArtifacts ?? []), ...accepted];
|
|
86
123
|
}
|
|
87
124
|
}
|
|
88
125
|
catch (error) {
|
|
89
|
-
warnings.push(
|
|
126
|
+
warnings.push(`scorer.deriveArtifacts threw (${sanitize(error instanceof Error ? error.message : String(error))}); dropped so the bundle stays verifiable.`);
|
|
90
127
|
}
|
|
91
128
|
}
|
|
92
129
|
return { failures };
|
|
93
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* A feedback candidate a scorer returned, accepted at the seam: the bundle's candidate shape with a
|
|
133
|
+
* non-empty summary. The browser and terminal seams both use it, so a candidate either seam drops
|
|
134
|
+
* never reaches a bundle.
|
|
135
|
+
*/
|
|
136
|
+
export function isAdapterFeedbackCandidate(value) {
|
|
137
|
+
return isRunFeedbackCandidate(value) && value.summary.trim().length > 0;
|
|
138
|
+
}
|
|
94
139
|
export function adapterScoreFailureMessage(bundle) {
|
|
95
140
|
return bundle.adapterScore?.status === "fail"
|
|
96
141
|
? `Adapter scorer failed the run: ${bundle.adapterScore.summary}`
|
|
@@ -115,62 +160,6 @@ export function frozenBundleView(bundle) {
|
|
|
115
160
|
freeze(clone);
|
|
116
161
|
return clone;
|
|
117
162
|
}
|
|
118
|
-
function isAdapterScoreShape(value) {
|
|
119
|
-
return (typeof value === "object" &&
|
|
120
|
-
value !== null &&
|
|
121
|
-
!Array.isArray(value) &&
|
|
122
|
-
value.schema === "humanish.adapter-score.v1" &&
|
|
123
|
-
typeof value.namespace === "string" &&
|
|
124
|
-
value.namespace.trim().length > 0 &&
|
|
125
|
-
["pass", "partial", "fail"].includes(value.status) &&
|
|
126
|
-
typeof value.score === "number" &&
|
|
127
|
-
Number.isFinite(value.score) &&
|
|
128
|
-
typeof value.summary === "string" &&
|
|
129
|
-
(value.data === undefined ||
|
|
130
|
-
(typeof value.data === "object" &&
|
|
131
|
-
value.data !== null &&
|
|
132
|
-
!Array.isArray(value.data))));
|
|
133
|
-
}
|
|
134
|
-
function isAdapterFeedbackCandidateShape(value) {
|
|
135
|
-
if (!isRecord(value))
|
|
136
|
-
return false;
|
|
137
|
-
const candidate = value;
|
|
138
|
-
if (candidate.schema !== "humanish.feedback-candidate.v1" ||
|
|
139
|
-
typeof candidate.id !== "string" ||
|
|
140
|
-
typeof candidate.run_id !== "string" ||
|
|
141
|
-
(candidate.stream_id !== undefined && typeof candidate.stream_id !== "string") ||
|
|
142
|
-
typeof candidate.adapter_id !== "string" ||
|
|
143
|
-
typeof candidate.scenario_id !== "string" ||
|
|
144
|
-
typeof candidate.persona_id !== "string" ||
|
|
145
|
-
!isFeedbackActor(candidate.actor) ||
|
|
146
|
-
!isFeedbackSubstrate(candidate.substrate) ||
|
|
147
|
-
!isFeedbackFailureOwner(candidate.failure_owner) ||
|
|
148
|
-
typeof candidate.summary !== "string" ||
|
|
149
|
-
candidate.summary.trim().length === 0 ||
|
|
150
|
-
typeof candidate.expected !== "string" ||
|
|
151
|
-
typeof candidate.actual !== "string" ||
|
|
152
|
-
!Array.isArray(candidate.evidence) ||
|
|
153
|
-
!candidate.evidence.every(isFeedbackEvidence) ||
|
|
154
|
-
!isRecord(candidate.redaction) ||
|
|
155
|
-
candidate.redaction.status !== "passed" ||
|
|
156
|
-
typeof candidate.redaction.notes !== "string" ||
|
|
157
|
-
!isFeedbackIdempotencyKey(candidate.idempotency_key) ||
|
|
158
|
-
!isFeedbackNextState(candidate.proposed_next_state) ||
|
|
159
|
-
!Array.isArray(candidate.acceptance_proof) ||
|
|
160
|
-
!candidate.acceptance_proof.every((item) => typeof item === "string")) {
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
if (candidate.adapter !== undefined) {
|
|
164
|
-
const adapter = candidate.adapter;
|
|
165
|
-
if (!isRecord(adapter) ||
|
|
166
|
-
typeof adapter.namespace !== "string" ||
|
|
167
|
-
adapter.namespace.trim().length === 0 ||
|
|
168
|
-
!isRecord(adapter.data)) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
163
|
function isAdapterArtifactShape(value) {
|
|
175
164
|
if (!isRecord(value))
|
|
176
165
|
return false;
|
|
@@ -186,9 +175,6 @@ function isAdapterArtifactShape(value) {
|
|
|
186
175
|
typeof artifact.note === "string" &&
|
|
187
176
|
artifact.note.trim().length > 0);
|
|
188
177
|
}
|
|
189
|
-
function isRecord(value) {
|
|
190
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
191
|
-
}
|
|
192
178
|
function isSafeRelativeArtifactPath(value) {
|
|
193
179
|
return (value.trim().length > 0 &&
|
|
194
180
|
!path.isAbsolute(value) &&
|
|
@@ -204,50 +190,3 @@ function isAdapterArtifactKind(value) {
|
|
|
204
190
|
value === "filesystem" ||
|
|
205
191
|
value === "summary");
|
|
206
192
|
}
|
|
207
|
-
function isFeedbackActor(value) {
|
|
208
|
-
return (value === "codex-tui" ||
|
|
209
|
-
value === "codex-exec" ||
|
|
210
|
-
value === "codex-app-server" ||
|
|
211
|
-
value === "computer-use" ||
|
|
212
|
-
value === "synthetic-dry-run" ||
|
|
213
|
-
value === "unknown");
|
|
214
|
-
}
|
|
215
|
-
function isFeedbackSubstrate(value) {
|
|
216
|
-
return (value === "e2b-desktop" ||
|
|
217
|
-
value === "local-desktop" ||
|
|
218
|
-
value === "e2b-terminal" ||
|
|
219
|
-
value === "local-filesystem" ||
|
|
220
|
-
value === "codex-app-server" ||
|
|
221
|
-
value === "unknown");
|
|
222
|
-
}
|
|
223
|
-
function isFeedbackFailureOwner(value) {
|
|
224
|
-
return (value === "harness" ||
|
|
225
|
-
value === "target-app" ||
|
|
226
|
-
value === "actor" ||
|
|
227
|
-
value === "environment" ||
|
|
228
|
-
value === "unknown");
|
|
229
|
-
}
|
|
230
|
-
function isFeedbackNextState(value) {
|
|
231
|
-
return (value === "watch" ||
|
|
232
|
-
value === "adapter-hardening" ||
|
|
233
|
-
value === "target-app-setup" ||
|
|
234
|
-
value === "actor-auth" ||
|
|
235
|
-
value === "setup-quality-review" ||
|
|
236
|
-
value === "study-quality-review");
|
|
237
|
-
}
|
|
238
|
-
function isFeedbackEvidence(value) {
|
|
239
|
-
if (!isRecord(value))
|
|
240
|
-
return false;
|
|
241
|
-
return (typeof value.path === "string" &&
|
|
242
|
-
value.path.length > 0 &&
|
|
243
|
-
!path.isAbsolute(value.path) &&
|
|
244
|
-
!value.path.includes("://") &&
|
|
245
|
-
!value.path.includes("..") &&
|
|
246
|
-
(value.kind === "review" ||
|
|
247
|
-
value.kind === "state" ||
|
|
248
|
-
value.kind === "log" ||
|
|
249
|
-
value.kind === "trace" ||
|
|
250
|
-
value.kind === "screenshot" ||
|
|
251
|
-
value.kind === "filesystem") &&
|
|
252
|
-
typeof value.note === "string");
|
|
253
|
-
}
|
|
@@ -3,20 +3,40 @@ import type { TerminalProductScoringContext } from "../routes/terminal/types.js"
|
|
|
3
3
|
import type { LabRoute } from "./plan.js";
|
|
4
4
|
import type { RunAdapterArtifact, RunAdapterScore, RunFeedbackCandidate, RunScorerProvenance } from "../run/bundle.js";
|
|
5
5
|
/** The read-model context a loaded scorer sees — the terminal or browser scoring context. The module
|
|
6
|
-
* narrows it at runtime (`"product" in ctx` ⇒ terminal; `"
|
|
6
|
+
* narrows it at runtime (`"product" in ctx` ⇒ terminal; `"route" in ctx` ⇒ browser). */
|
|
7
7
|
export type AdapterScoringContext = TerminalProductScoringContext | BrowserLabScoringContext;
|
|
8
8
|
/**
|
|
9
9
|
* The adopter-facing scorer module contract (#316). Export any subset of these from a `.mjs` (or a
|
|
10
10
|
* `.js`/`.cjs` whose package.json type matches) — named exports OR a single default object. The
|
|
11
11
|
* loader wires ONLY these three; an exported `executor`/`env`/`provisionSubject`/`costProbe` is never
|
|
12
12
|
* picked up (the whitelist is the scope guard). A module exporting NONE of them is a hard load error.
|
|
13
|
+
*
|
|
14
|
+
* `C` is the context `score` and `deriveFeedback` read: `BrowserLabScoringContext` for a scorer
|
|
15
|
+
* written for computer use and shared world, `TerminalProductScoringContext` for one written for
|
|
16
|
+
* terminal runs, or the default union for one that narrows at runtime.
|
|
13
17
|
*/
|
|
14
|
-
export interface AdapterScorerModule {
|
|
15
|
-
score?: (ctx:
|
|
16
|
-
deriveFeedback?: (ctx:
|
|
17
|
-
/** Browser-route only; inert on the terminal route
|
|
18
|
+
export interface AdapterScorerModule<C extends AdapterScoringContext = AdapterScoringContext> {
|
|
19
|
+
score?: (ctx: C) => RunAdapterScore | Promise<RunAdapterScore>;
|
|
20
|
+
deriveFeedback?: (ctx: C) => RunFeedbackCandidate[] | Promise<RunFeedbackCandidate[]>;
|
|
21
|
+
/** Browser-route only; inert on the terminal route, whose TerminalScorer has no artifacts seam. */
|
|
18
22
|
deriveArtifacts?: (ctx: BrowserLabScoringContext) => RunAdapterArtifact[] | Promise<RunAdapterArtifact[]>;
|
|
19
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* A scorer written for computer use and shared world, as `RunLabOptions.scorer` takes it. Those
|
|
26
|
+
* routes pass the browser context; another route that calls it passes a context it was not written
|
|
27
|
+
* for. The call states the kind, so the module itself needs no cast.
|
|
28
|
+
*/
|
|
29
|
+
export declare function browserScorer(scorer: AdapterScorerModule<BrowserLabScoringContext>): AdapterScorerModule;
|
|
30
|
+
/** A scorer written for terminal runs, as `RunLabOptions.scorer` takes it (see browserScorer). */
|
|
31
|
+
export declare function terminalScorer(scorer: AdapterScorerModule<TerminalProductScoringContext>): AdapterScorerModule;
|
|
32
|
+
/**
|
|
33
|
+
* The scorer as a computer-use or shared-world run calls it, with the browser context. The caller
|
|
34
|
+
* chose the context it wrote the scorer for; only the route knows which context it passes, so the
|
|
35
|
+
* narrowing is here. A terminal-typed scorer on a browser route reads fields the context lacks.
|
|
36
|
+
*/
|
|
37
|
+
export declare function browserRouteScorer(scorer: AdapterScorerModule): AdapterScorerModule<BrowserLabScoringContext>;
|
|
38
|
+
/** The scorer as a terminal run calls it, with the terminal context (see browserRouteScorer). */
|
|
39
|
+
export declare function terminalRouteScorer(scorer: AdapterScorerModule): AdapterScorerModule<TerminalProductScoringContext>;
|
|
20
40
|
type AdapterScorerLoadErrorCode = "HUMANISH_LAB_SCORER_BAD_REF" | "HUMANISH_LAB_SCORER_NOT_FOUND" | "HUMANISH_LAB_SCORER_LOAD_FAILED" | "HUMANISH_LAB_SCORER_NO_HOOKS" | "HUMANISH_LAB_SCORER_UNSUPPORTED_BACKEND";
|
|
21
41
|
export type AdapterScorerLoadResult = {
|
|
22
42
|
ok: true;
|
|
@@ -19,6 +19,30 @@ import path from "node:path";
|
|
|
19
19
|
import { pathToFileURL } from "node:url";
|
|
20
20
|
import { digestText, redactText } from "../evidence/redaction.js";
|
|
21
21
|
import { prepareSelectedOutputDirectory, readContainedRegularFile, } from "../run/contained-output.js";
|
|
22
|
+
/**
|
|
23
|
+
* A scorer written for computer use and shared world, as `RunLabOptions.scorer` takes it. Those
|
|
24
|
+
* routes pass the browser context; another route that calls it passes a context it was not written
|
|
25
|
+
* for. The call states the kind, so the module itself needs no cast.
|
|
26
|
+
*/
|
|
27
|
+
export function browserScorer(scorer) {
|
|
28
|
+
return scorer;
|
|
29
|
+
}
|
|
30
|
+
/** A scorer written for terminal runs, as `RunLabOptions.scorer` takes it (see browserScorer). */
|
|
31
|
+
export function terminalScorer(scorer) {
|
|
32
|
+
return scorer;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The scorer as a computer-use or shared-world run calls it, with the browser context. The caller
|
|
36
|
+
* chose the context it wrote the scorer for; only the route knows which context it passes, so the
|
|
37
|
+
* narrowing is here. A terminal-typed scorer on a browser route reads fields the context lacks.
|
|
38
|
+
*/
|
|
39
|
+
export function browserRouteScorer(scorer) {
|
|
40
|
+
return scorer;
|
|
41
|
+
}
|
|
42
|
+
/** The scorer as a terminal run calls it, with the terminal context (see browserRouteScorer). */
|
|
43
|
+
export function terminalRouteScorer(scorer) {
|
|
44
|
+
return scorer;
|
|
45
|
+
}
|
|
22
46
|
/** The routes whose hooks bag can carry the loaded scorer. A declared scorer on ANY other route
|
|
23
47
|
* (scripted or preview) aborts at load — a gate that cannot run must never green-pass. */
|
|
24
48
|
const SCORER_CAPABLE_ROUTES = new Set([
|
|
@@ -3,3 +3,5 @@ import type { LabConfig } from "./types.js";
|
|
|
3
3
|
export declare function compositionReason(config: LabConfig): string | null;
|
|
4
4
|
/** Why a this-repo lab cannot run live. The parser and the preview planner both refuse with it. */
|
|
5
5
|
export declare const THIS_REPO_DRY_RUN_ONLY = "this-repo labs are dry-run only; use a clone or app-url subject for a live run.";
|
|
6
|
+
/** A desktop-cli subject with no product to study. The computer-use planner checks this too. */
|
|
7
|
+
export declare function desktopCliProductReason(config: LabConfig): string | null;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// Which subject, target and actor compositions a lab may declare. Each rule returns the refusal
|
|
2
2
|
// message for the first thing its composition gets wrong, or null. compositionReason runs them in
|
|
3
|
-
// the parser's order
|
|
4
|
-
//
|
|
3
|
+
// the parser's order, and only parseLabConfig calls it. planLab does not: each route planner checks
|
|
4
|
+
// a library caller's config itself, under its route's error codes. The planners call the shared
|
|
5
|
+
// checks in lab/validation.ts and desktopCliProductReason below. The other subject rules here have
|
|
6
|
+
// planner counterparts whose conditions and wording differ (clone serve and repo, local-tree
|
|
7
|
+
// target, in-process fan-out, loopback targets, scripted scenario.ref).
|
|
5
8
|
import { isLoopbackUrl } from "./parse/subject.js";
|
|
6
9
|
import { REPO_SLUG_PATTERN } from "./parse/values.js";
|
|
7
10
|
import { declaredTargets } from "./plan-participants.js";
|
|
@@ -18,10 +21,10 @@ export function compositionReason(config) {
|
|
|
18
21
|
cloneTargetValidationReason(config) ??
|
|
19
22
|
cloneComputerUseValidationReason(config) ??
|
|
20
23
|
localTreeValidationReason(config) ??
|
|
21
|
-
// Independent computer-use
|
|
24
|
+
// Independent computer-use participants: the roster contract on every route that resolves to cua.
|
|
22
25
|
(isComputerUseComposition(config) ? cuaLaneValidationReason(config) : null) ??
|
|
23
26
|
// Whenever shared world is declared, not only when it routes, so a half-declared shared world
|
|
24
|
-
// fails with a precise reason instead of running as independent
|
|
27
|
+
// fails with a precise reason instead of running as independent participants.
|
|
25
28
|
(config.subject.topology === "shared-world" ? sharedWorldValidationReason(config) : null) ??
|
|
26
29
|
desktopCliValidationReason(config) ??
|
|
27
30
|
terminalValidationReason(config) ??
|
|
@@ -42,12 +45,12 @@ function thisRepoValidationReason(config) {
|
|
|
42
45
|
}
|
|
43
46
|
return null;
|
|
44
47
|
}
|
|
45
|
-
// local-app route: an already-running
|
|
48
|
+
// local-app route: an already-running local dev server driven in-process via a custom
|
|
46
49
|
// CuaExecutor (no clone, no E2B desktop). Parse-validated fail-closed: a computer-use actor
|
|
47
|
-
// only, execution.target local or absent (
|
|
50
|
+
// only, execution.target local or absent (never e2b-desktop, because the route exists to skip the
|
|
48
51
|
// desktop), and no public-target policy (it is always loopback; the loopback shape was already
|
|
49
|
-
// enforced in parseSubject). The actual "no
|
|
50
|
-
// engine-time decision (the parser cannot know whether a library caller will pass
|
|
52
|
+
// enforced in parseSubject). The actual "no inProcess executor supplied" case is inherently an
|
|
53
|
+
// engine-time decision (the parser cannot know whether a library caller will pass one), so
|
|
51
54
|
// it fails closed in runCuaActorLab with HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR.
|
|
52
55
|
function localAppValidationReason(config) {
|
|
53
56
|
if (config.subject.source === "local-app") {
|
|
@@ -70,7 +73,7 @@ function localAppValidationReason(config) {
|
|
|
70
73
|
}
|
|
71
74
|
return null;
|
|
72
75
|
}
|
|
73
|
-
// app-url routes: the actor type is a
|
|
76
|
+
// app-url routes: the actor type is a real dispatch key (registry-resolved). The actor lane
|
|
74
77
|
// picks the substrate: a scripted-browser actor runs locally against the declared loopback
|
|
75
78
|
// app; a computer-use actor drives a hosted desktop browser. Fail closed on mis-configs.
|
|
76
79
|
function appUrlValidationReason(config) {
|
|
@@ -105,9 +108,9 @@ function appUrlValidationReason(config) {
|
|
|
105
108
|
if (!actorResolvesToComputerUse(type)) {
|
|
106
109
|
return `actors[0].type must be a registered computer-use actor for app-url × e2b-desktop labs (one of: ${registeredComputerUseActors().join(", ")}); for local scripted execution use a registered scripted-browser actor (${registeredScriptedBrowserActors().join(", ")}). Got "${type}".`;
|
|
107
110
|
}
|
|
108
|
-
// Multi-
|
|
109
|
-
// cross-validation below enforces lanes
|
|
110
|
-
//
|
|
111
|
+
// Multi-participant fan-out is consumed on this route (`per-lane-worlds`; the shared cua
|
|
112
|
+
// cross-validation below enforces `lanes`/`count` XOR rules, the 16 cap, and the
|
|
113
|
+
// per-participant target gates, and the allowPublicTargets+N>1 rejection for ambiguous one-target
|
|
111
114
|
// fan-out).
|
|
112
115
|
// Loopback by default; an owner may declare a public/preview target via policies.
|
|
113
116
|
const targets = [config.subject.appUrl ?? "", ...declaredTargets(config)];
|
|
@@ -175,7 +178,7 @@ function scriptedBrowserValidationReason(config) {
|
|
|
175
178
|
return null;
|
|
176
179
|
}
|
|
177
180
|
// clone × e2b-desktop disambiguates on the actor lane: a computer-use actor means the lab
|
|
178
|
-
// clones
|
|
181
|
+
// clones and serves the subject in-sandbox, then drives it. Scripted-browser actors were checked
|
|
179
182
|
// above.
|
|
180
183
|
function cloneComputerUseValidationReason(config) {
|
|
181
184
|
if (config.subject.source === "clone" &&
|
|
@@ -191,15 +194,15 @@ function cloneComputerUseValidationReason(config) {
|
|
|
191
194
|
if (!REPO_SLUG_PATTERN.test(repo)) {
|
|
192
195
|
return `subject.repos[0] must be an owner/repo slug (got "${repo}").`;
|
|
193
196
|
}
|
|
194
|
-
// Fan-out is
|
|
195
|
-
// desktop (per-lane
|
|
196
|
-
// lanes
|
|
197
|
+
// Fan-out is consumed here: N participants each clone the same single repo into their own
|
|
198
|
+
// E2B desktop (`per-lane-worlds`). The shared cua cross-validation below enforces the
|
|
199
|
+
// `lanes`/`count` rules and the 16 cap; the single-repo rule above is unchanged.
|
|
197
200
|
}
|
|
198
201
|
return null;
|
|
199
202
|
}
|
|
200
203
|
// local-tree route: packs and uploads the operator's own working tree, then serves it exactly
|
|
201
204
|
// like a computer-use clone subject. The scripted-browser route has no packed-working-tree
|
|
202
|
-
// mode, so e2b-desktop + a computer-use actor are the
|
|
205
|
+
// mode, so e2b-desktop + a computer-use actor are the only combination this source supports.
|
|
203
206
|
// `subject.serve` is already required at parse time (parseSubject); the repos/clone rejection
|
|
204
207
|
// also already happened there (local-tree never carries git slugs).
|
|
205
208
|
function localTreeValidationReason(config) {
|
|
@@ -215,17 +218,23 @@ function localTreeValidationReason(config) {
|
|
|
215
218
|
}
|
|
216
219
|
// desktop-cli route: a computer-use participant studies a CLI/TUI the way a person does — at a
|
|
217
220
|
// desktop, in a terminal window, by looking at it. The sibling of terminal-product, and the
|
|
218
|
-
// distinction is the
|
|
221
|
+
// distinction is the population: terminal-product sends an autonomous agent
|
|
219
222
|
// through a pipe with stdin disabled, which is the honest way to study what an agent meets and
|
|
220
223
|
// structurally cannot study an interactive surface. This route sends someone who can see it.
|
|
221
224
|
//
|
|
222
225
|
// Fail-closed on the pairing (invariant 6): a hosted desktop and a computer-use actor, because
|
|
223
226
|
// "watch a person use a terminal" is not something the other substrates can do.
|
|
227
|
+
/** A desktop-cli subject with no product to study. The computer-use planner checks this too. */
|
|
228
|
+
export function desktopCliProductReason(config) {
|
|
229
|
+
return config.subject.source === "desktop-cli" && config.subject.product?.name === undefined
|
|
230
|
+
? "desktop-cli subjects need `subject.product.name` — the CLI the participant is being asked to use."
|
|
231
|
+
: null;
|
|
232
|
+
}
|
|
224
233
|
function desktopCliValidationReason(config) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
const productReason = desktopCliProductReason(config);
|
|
235
|
+
if (productReason)
|
|
236
|
+
return productReason;
|
|
237
|
+
if (config.subject.source === "desktop-cli" && config.subject.product !== undefined) {
|
|
229
238
|
if (config.execution?.target !== undefined && config.execution.target !== "e2b-desktop") {
|
|
230
239
|
return "desktop-cli subjects are studied at a hosted desktop — set `execution.target: e2b-desktop` or omit it.";
|
|
231
240
|
}
|
|
@@ -239,11 +248,11 @@ function desktopCliValidationReason(config) {
|
|
|
239
248
|
}
|
|
240
249
|
return null;
|
|
241
250
|
}
|
|
242
|
-
// terminal-product route: a real autonomous agent studies a CLI/product from
|
|
251
|
+
// terminal-product route: a real autonomous agent studies a CLI/product from public surfaces
|
|
243
252
|
// inside an E2B shell. Fail-closed (invariant 6 — a field that cannot act on this route is an
|
|
244
253
|
// honest parse error): a registered terminal actor only, execution.target e2b-terminal or absent
|
|
245
|
-
// (absent defaults to e2b-terminal — the only honest target for an in-sandbox agent),
|
|
246
|
-
//
|
|
254
|
+
// (absent defaults to e2b-terminal — the only honest target for an in-sandbox agent), one
|
|
255
|
+
// participant until fan-out lands.
|
|
247
256
|
function terminalValidationReason(config) {
|
|
248
257
|
if (config.subject.source === "terminal-product") {
|
|
249
258
|
const type = config.actors[0]?.type ?? "";
|
|
@@ -258,7 +267,7 @@ function terminalValidationReason(config) {
|
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
269
|
else if (config.execution?.target === "e2b-terminal") {
|
|
261
|
-
// e2b-terminal is the terminal-product substrate
|
|
270
|
+
// e2b-terminal is the terminal-product substrate only. Any other source declaring it is a
|
|
262
271
|
// mis-config — reject, never silently mishandle (mirrors app-url's e2b-desktop pairing rule).
|
|
263
272
|
return "`execution.target: e2b-terminal` requires `subject.source: terminal-product` with a registered terminal actor.";
|
|
264
273
|
}
|
package/dist/lab/config.js
CHANGED
|
@@ -1,59 +1,61 @@
|
|
|
1
|
-
// humanish.lab.v2
|
|
1
|
+
// humanish.lab.v2: a lab is a composition over code primitives. There is no hardcoded lab kind.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// Scope (read before trusting field names): the engine routes by
|
|
4
4
|
// subject.source × execution.target (disambiguated by the actor lane where both axes
|
|
5
5
|
// collide) and consumes a deliberately small set of fields:
|
|
6
6
|
// subject.source/repos/appUrl/serve/env/state/clone.{depth,fanout,keep}, actors[0].count,
|
|
7
7
|
// execution.target + execution.desktop.codexAppServer, scenario.mode,
|
|
8
8
|
// policies.redactRepos, defaults.open.
|
|
9
9
|
// On the computer-use routes (app-url × e2b-desktop, and clone × e2b-desktop with a
|
|
10
|
-
// computer-use actor), `actors[0].type`
|
|
10
|
+
// computer-use actor), `actors[0].type` is load-bearing: it must resolve to a registered
|
|
11
11
|
// computer-use actor, and that descriptor runs the session. Those routes also consume
|
|
12
12
|
// actors[0].{mission,persona,laneFocus.instruction,model,reasoningEffort}, execution.timeoutMs,
|
|
13
13
|
// execution.desktop.{browser,resolution,sandboxTimeoutMs}, and (clone)
|
|
14
14
|
// subject.{serve,env,state,clone.depth}.
|
|
15
15
|
// On the scripted-browser route (app-url × local-or-absent, or clone × e2b-desktop, with a
|
|
16
16
|
// registered scripted-browser actor), `actors[0].type` is equally load-bearing, and the route
|
|
17
|
-
// consumes scenario.ref (
|
|
17
|
+
// consumes scenario.ref (required there, because the committed scenario's browser steps are what the
|
|
18
18
|
// actor executes), actors[0].{persona,count}, and execution.timeoutMs. On the provisioned
|
|
19
19
|
// clone slice it also consumes subject.{repos,serve,env,state,exposure,clone.depth} and
|
|
20
20
|
// execution.desktop.template. actors[0].{mission,laneFocus,model} are inert on that route
|
|
21
21
|
// because no model runs, and most execution.desktop.* fields remain forward-declared (device
|
|
22
22
|
// presets belong to the cua route — scripted surfaces are the driver's own desktop/mobile
|
|
23
|
-
// viewports where isMobile/DSF genuinely
|
|
24
|
-
// On the other routes those fields remain
|
|
23
|
+
// viewports where isMobile/DSF genuinely render via playwright emulation).
|
|
24
|
+
// On the other routes those fields remain forward-declared and are not yet consumed:
|
|
25
25
|
// parseLabConfig emits a warning listing any such field that is set, so `lab inspect` shows
|
|
26
26
|
// the truth.
|
|
27
27
|
//
|
|
28
28
|
// NOTE on actors[0].count: it now carries ROUTE-SPECIFIC meanings — synthetic route: simCount;
|
|
29
29
|
// scripted-browser route: surface roster {1 = desktop, 2 = desktop + mobile}, default 1 (the
|
|
30
|
-
// defaults-table single-
|
|
31
|
-
// E2B route: the
|
|
32
|
-
// capped at 16; the in-process/local-app cua route stays single
|
|
30
|
+
// defaults-table single-participant row governs; count: 2 is the declared override); computer-use
|
|
31
|
+
// E2B route: the homogeneous fan-out participant count (N identical participants, each its own E2B
|
|
32
|
+
// desktop), capped at 16; the in-process/local-app cua route stays single-participant (no E2B to
|
|
33
|
+
// fan out).
|
|
33
34
|
//
|
|
34
35
|
// NOTE on actors[0].lanes / actors[0].roster (computer-use E2B route, this slice): a
|
|
35
|
-
//
|
|
36
|
-
// independent E2B desktop (per-lane
|
|
36
|
+
// differentiated fan-out roster: each `{ id?, persona?, device?, instruction?, target? }` becomes one
|
|
37
|
+
// independent E2B desktop (`per-lane-worlds`, the default topology). `roster[]` is parser sugar for
|
|
37
38
|
// repeated groups and is normalized into `lanes[]` before the engine sees it. `lanes|roster` XOR
|
|
38
|
-
// `count` (declare a differentiated roster
|
|
39
|
-
// XOR `actors[0].laneFocus` (
|
|
40
|
-
// raw `execution.desktop.resolution`. `execution.concurrency` bounds in-flight
|
|
41
|
-
//
|
|
39
|
+
// `count` (declare a differentiated roster or a homogeneous count, never both); `lanes|roster`
|
|
40
|
+
// XOR `actors[0].laneFocus` (each entry's `instruction` is the roster's steer); `lanes[].device` XOR
|
|
41
|
+
// raw `execution.desktop.resolution`. `execution.concurrency` bounds in-flight participants (default:
|
|
42
|
+
// the participant count, all at once; env HUMANISH_CUA_MAX_CONCURRENCY may only lower it, per invariant
|
|
42
43
|
// 3). On every non-cua route normalized `lanes` are inert (warned). subject.clone.fanout is
|
|
43
|
-
//
|
|
44
|
-
// URL this
|
|
44
|
+
// rejected on the cua route. `lanes[].target` is app-url × computer-use only: an absolute browser
|
|
45
|
+
// URL this participant opens instead of `subject.appUrl`; it is the generic setup-produced-target
|
|
45
46
|
// handoff, not a service topology primitive.
|
|
46
47
|
//
|
|
47
|
-
// There is deliberately
|
|
48
|
+
// There is deliberately no v1 compatibility: v1 had zero real users. Breaking schema changes
|
|
48
49
|
// bump the version honestly.
|
|
49
50
|
import { isLocalBrowserLab, localBrowserDefaults, localBrowserUnsupportedReason, } from "../substrates/local/runtime-config.js";
|
|
51
|
+
import { isRecord } from "../run/type-guards.js";
|
|
50
52
|
import { compositionReason } from "./composition-rules.js";
|
|
51
53
|
import { findUnknownLabKey } from "./keys.js";
|
|
52
54
|
import { parseActors, rosterOf } from "./parse/actors.js";
|
|
53
55
|
import { parseComms, recipientParticipantId } from "./parse/comms.js";
|
|
54
56
|
import { parseDefaults, parseExecution, parsePersonas, parsePolicies, parseReview, parseScenario, } from "./parse/execution.js";
|
|
55
57
|
import { parseSubject } from "./parse/subject.js";
|
|
56
|
-
import { invalid,
|
|
58
|
+
import { invalid, optionalStr, str } from "./parse/values.js";
|
|
57
59
|
import { isComputerUseComposition, isSharedWorldComposition } from "./routing.js";
|
|
58
60
|
import { declaredParticipantIds } from "./plan-participants.js";
|
|
59
61
|
import { ID_PATTERN, LAB_CONFIG_SCHEMA, } from "./types.js";
|
|
@@ -150,7 +152,7 @@ export function parseLabConfig(raw) {
|
|
|
150
152
|
return invalid(scenarioCapsReason);
|
|
151
153
|
// All-parallel default (#350): a multi-seat lab that does not declare execution.concurrency runs
|
|
152
154
|
// every seat at once; the declared field is a cap the author chose, never a mode. Independent
|
|
153
|
-
// computer-use
|
|
155
|
+
// computer-use participants resolve that default from the final participant count when they plan, after any
|
|
154
156
|
// --count override, so the parser leaves it unset for them. A shared world's roster is fixed, so
|
|
155
157
|
// its default is filled here for the envelopes and warnings that read the parsed config.
|
|
156
158
|
{
|
|
@@ -161,12 +163,12 @@ export function parseLabConfig(raw) {
|
|
|
161
163
|
config.execution = { ...config.execution, concurrency: participantCount };
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
|
-
// Email that just works (#351): the funnel's
|
|
165
|
-
// instruction, gated on recipients[]. Guessed
|
|
166
|
-
// from a single-
|
|
167
|
-
// signal. Omitted recipients are therefore
|
|
168
|
-
// recipient naming an unknown
|
|
169
|
-
// recipients covering zero
|
|
166
|
+
// Email that just works (#351): the funnel's only handoff to an actor is the per-participant
|
|
167
|
+
// inbox instruction, gated on recipients[]. Guessed participant ids broke a field run —
|
|
168
|
+
// recipients copied from a single-participant example matched nothing, so every actor was left inbox-blind with zero
|
|
169
|
+
// signal. Omitted recipients are therefore filled (one deterministic address per participant);
|
|
170
|
+
// a recipient naming an unknown participant is a hard error listing the real ids; declared
|
|
171
|
+
// recipients covering zero participants are a hard error (a guaranteed-dead funnel).
|
|
170
172
|
const receivingReason = receivingEmailValidationReason(config);
|
|
171
173
|
if (receivingReason)
|
|
172
174
|
return invalid(receivingReason);
|
|
@@ -4,9 +4,9 @@ export interface DevicePreset {
|
|
|
4
4
|
width: number;
|
|
5
5
|
/** Requested device height, used for the hosted physical screen. */
|
|
6
6
|
height: number;
|
|
7
|
-
/** Mobile identity; enables emulation only when the hosted
|
|
7
|
+
/** Mobile identity; enables emulation only when the hosted participant explicitly opts in. */
|
|
8
8
|
isMobile: boolean;
|
|
9
|
-
/** Requested DPR; applied on hosted mobile
|
|
9
|
+
/** Requested DPR; applied on hosted mobile participants only with opt-in CDP emulation. */
|
|
10
10
|
deviceScaleFactor: number;
|
|
11
11
|
}
|
|
12
12
|
/**
|