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,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([
|
|
@@ -21,10 +21,10 @@ export function compositionReason(config) {
|
|
|
21
21
|
cloneTargetValidationReason(config) ??
|
|
22
22
|
cloneComputerUseValidationReason(config) ??
|
|
23
23
|
localTreeValidationReason(config) ??
|
|
24
|
-
// Independent computer-use
|
|
24
|
+
// Independent computer-use participants: the roster contract on every route that resolves to cua.
|
|
25
25
|
(isComputerUseComposition(config) ? cuaLaneValidationReason(config) : null) ??
|
|
26
26
|
// Whenever shared world is declared, not only when it routes, so a half-declared shared world
|
|
27
|
-
// fails with a precise reason instead of running as independent
|
|
27
|
+
// fails with a precise reason instead of running as independent participants.
|
|
28
28
|
(config.subject.topology === "shared-world" ? sharedWorldValidationReason(config) : null) ??
|
|
29
29
|
desktopCliValidationReason(config) ??
|
|
30
30
|
terminalValidationReason(config) ??
|
|
@@ -45,12 +45,12 @@ function thisRepoValidationReason(config) {
|
|
|
45
45
|
}
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
|
-
// local-app route: an already-running
|
|
48
|
+
// local-app route: an already-running local dev server driven in-process via a custom
|
|
49
49
|
// CuaExecutor (no clone, no E2B desktop). Parse-validated fail-closed: a computer-use actor
|
|
50
|
-
// only, execution.target local or absent (
|
|
50
|
+
// only, execution.target local or absent (never e2b-desktop, because the route exists to skip the
|
|
51
51
|
// desktop), and no public-target policy (it is always loopback; the loopback shape was already
|
|
52
|
-
// enforced in parseSubject). The actual "no
|
|
53
|
-
// 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
|
|
54
54
|
// it fails closed in runCuaActorLab with HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR.
|
|
55
55
|
function localAppValidationReason(config) {
|
|
56
56
|
if (config.subject.source === "local-app") {
|
|
@@ -73,7 +73,7 @@ function localAppValidationReason(config) {
|
|
|
73
73
|
}
|
|
74
74
|
return null;
|
|
75
75
|
}
|
|
76
|
-
// 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
|
|
77
77
|
// picks the substrate: a scripted-browser actor runs locally against the declared loopback
|
|
78
78
|
// app; a computer-use actor drives a hosted desktop browser. Fail closed on mis-configs.
|
|
79
79
|
function appUrlValidationReason(config) {
|
|
@@ -108,9 +108,9 @@ function appUrlValidationReason(config) {
|
|
|
108
108
|
if (!actorResolvesToComputerUse(type)) {
|
|
109
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}".`;
|
|
110
110
|
}
|
|
111
|
-
// Multi-
|
|
112
|
-
// cross-validation below enforces lanes
|
|
113
|
-
//
|
|
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
|
|
114
114
|
// fan-out).
|
|
115
115
|
// Loopback by default; an owner may declare a public/preview target via policies.
|
|
116
116
|
const targets = [config.subject.appUrl ?? "", ...declaredTargets(config)];
|
|
@@ -178,7 +178,7 @@ function scriptedBrowserValidationReason(config) {
|
|
|
178
178
|
return null;
|
|
179
179
|
}
|
|
180
180
|
// clone × e2b-desktop disambiguates on the actor lane: a computer-use actor means the lab
|
|
181
|
-
// clones
|
|
181
|
+
// clones and serves the subject in-sandbox, then drives it. Scripted-browser actors were checked
|
|
182
182
|
// above.
|
|
183
183
|
function cloneComputerUseValidationReason(config) {
|
|
184
184
|
if (config.subject.source === "clone" &&
|
|
@@ -194,15 +194,15 @@ function cloneComputerUseValidationReason(config) {
|
|
|
194
194
|
if (!REPO_SLUG_PATTERN.test(repo)) {
|
|
195
195
|
return `subject.repos[0] must be an owner/repo slug (got "${repo}").`;
|
|
196
196
|
}
|
|
197
|
-
// Fan-out is
|
|
198
|
-
// desktop (per-lane
|
|
199
|
-
// 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.
|
|
200
200
|
}
|
|
201
201
|
return null;
|
|
202
202
|
}
|
|
203
203
|
// local-tree route: packs and uploads the operator's own working tree, then serves it exactly
|
|
204
204
|
// like a computer-use clone subject. The scripted-browser route has no packed-working-tree
|
|
205
|
-
// 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.
|
|
206
206
|
// `subject.serve` is already required at parse time (parseSubject); the repos/clone rejection
|
|
207
207
|
// also already happened there (local-tree never carries git slugs).
|
|
208
208
|
function localTreeValidationReason(config) {
|
|
@@ -218,7 +218,7 @@ function localTreeValidationReason(config) {
|
|
|
218
218
|
}
|
|
219
219
|
// desktop-cli route: a computer-use participant studies a CLI/TUI the way a person does — at a
|
|
220
220
|
// desktop, in a terminal window, by looking at it. The sibling of terminal-product, and the
|
|
221
|
-
// distinction is the
|
|
221
|
+
// distinction is the population: terminal-product sends an autonomous agent
|
|
222
222
|
// through a pipe with stdin disabled, which is the honest way to study what an agent meets and
|
|
223
223
|
// structurally cannot study an interactive surface. This route sends someone who can see it.
|
|
224
224
|
//
|
|
@@ -248,11 +248,11 @@ function desktopCliValidationReason(config) {
|
|
|
248
248
|
}
|
|
249
249
|
return null;
|
|
250
250
|
}
|
|
251
|
-
// 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
|
|
252
252
|
// inside an E2B shell. Fail-closed (invariant 6 — a field that cannot act on this route is an
|
|
253
253
|
// honest parse error): a registered terminal actor only, execution.target e2b-terminal or absent
|
|
254
|
-
// (absent defaults to e2b-terminal — the only honest target for an in-sandbox agent),
|
|
255
|
-
//
|
|
254
|
+
// (absent defaults to e2b-terminal — the only honest target for an in-sandbox agent), one
|
|
255
|
+
// participant until fan-out lands.
|
|
256
256
|
function terminalValidationReason(config) {
|
|
257
257
|
if (config.subject.source === "terminal-product") {
|
|
258
258
|
const type = config.actors[0]?.type ?? "";
|
|
@@ -267,7 +267,7 @@ function terminalValidationReason(config) {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
else if (config.execution?.target === "e2b-terminal") {
|
|
270
|
-
// e2b-terminal is the terminal-product substrate
|
|
270
|
+
// e2b-terminal is the terminal-product substrate only. Any other source declaring it is a
|
|
271
271
|
// mis-config — reject, never silently mishandle (mirrors app-url's e2b-desktop pairing rule).
|
|
272
272
|
return "`execution.target: e2b-terminal` requires `subject.source: terminal-product` with a registered terminal actor.";
|
|
273
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
|
/**
|
package/dist/lab/discover.js
CHANGED
|
@@ -7,6 +7,7 @@ import { parse } from "yaml";
|
|
|
7
7
|
import { parseLabConfig } from "./config.js";
|
|
8
8
|
import {} from "./types.js";
|
|
9
9
|
import { assertPreparedSelectedOutputDirectory, assertSafeOutputPathSegment, prepareSelectedOutputDirectory, readContainedRegularFile, } from "../run/contained-output.js";
|
|
10
|
+
import { isNodeError } from "../run/type-guards.js";
|
|
10
11
|
const LAB_LIST_SCHEMA = "humanish.lab-list.v1";
|
|
11
12
|
const LAB_INSPECT_SCHEMA = "humanish.lab-inspect.v1";
|
|
12
13
|
const committedLabsDir = path.join("humanish", "labs");
|
|
@@ -417,6 +418,3 @@ function relativeToCwd(cwd, filePath) {
|
|
|
417
418
|
const relative = path.relative(cwd, filePath);
|
|
418
419
|
return relative && !relative.startsWith("..") ? relative : filePath;
|
|
419
420
|
}
|
|
420
|
-
function isNodeError(error) {
|
|
421
|
-
return error instanceof Error && "code" in error;
|
|
422
|
-
}
|