humanish 0.107.0 → 0.108.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/ARCHITECTURE.md +22 -17
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +51 -44
- package/README.md +145 -172
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +8 -6
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +2 -2
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +16 -16
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/admission-limit.d.ts +1 -1
- package/dist/actors/computer-use/admission-limit.js +1 -1
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +10 -10
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/ending.d.ts +5 -5
- package/dist/actors/computer-use/loop/ending.js +7 -7
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +9 -9
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +1 -1
- package/dist/actors/computer-use/loop/session.js +3 -3
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +9 -8
- package/dist/actors/computer-use/loop/types.d.ts +25 -23
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +11 -8
- package/dist/actors/computer-use/openai-provider.js +45 -34
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/contract.d.ts +78 -43
- package/dist/actors/contract.js +29 -23
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +10 -9
- package/dist/actors/local-agent/cli.d.ts +8 -6
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +6 -6
- package/dist/actors/registry.d.ts +10 -10
- package/dist/actors/registry.js +18 -17
- package/dist/actors/scripted-browser/actor.d.ts +8 -8
- package/dist/actors/scripted-browser/actor.js +16 -16
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/service.js +5 -5
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +54 -33
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/lab-format.d.ts +5 -4
- package/dist/cli/commands/lab-format.js +35 -23
- package/dist/cli/commands/lab-route-computer-use.js +6 -7
- package/dist/cli/commands/lab-route-preview.js +4 -3
- package/dist/cli/commands/lab-route-shared-world.js +3 -3
- package/dist/cli/commands/lab-run.js +10 -11
- package/dist/cli/commands/lab-scorer.d.ts +2 -2
- package/dist/cli/commands/lab-scorer.js +1 -1
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.js +147 -108
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +137 -138
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +26 -21
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +182 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +21 -21
- package/dist/cli/commands/watch.js +60 -75
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +15 -5
- package/dist/cli/doctor.js +103 -48
- package/dist/cli/first-run-path.d.ts +12 -10
- package/dist/cli/first-run-path.js +30 -28
- package/dist/cli/io.d.ts +41 -6
- package/dist/cli/io.js +97 -22
- package/dist/cli/observer-follow.d.ts +2 -2
- package/dist/cli/observer-follow.js +5 -6
- package/dist/cli/orientation.d.ts +6 -3
- package/dist/cli/orientation.js +43 -39
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +109 -40
- package/dist/cli/telemetry.d.ts +15 -15
- package/dist/cli/telemetry.js +48 -40
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.js +2 -2
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +2 -2
- package/dist/comms/fake-inbox.js +2 -2
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +36 -37
- package/dist/comms/sandbox-catch.js +34 -35
- package/dist/comms/setup.js +42 -8
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +36 -78
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +7 -8
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/guest/chromium-text.js +2 -2
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/runtime.js +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +8 -6
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/lab/adapter-extension.d.ts +7 -7
- package/dist/lab/adapter-extension.js +13 -36
- package/dist/lab/adapter-scorer-loader.d.ts +7 -7
- package/dist/lab/adapter-scorer-loader.js +32 -32
- package/dist/lab/composition-rules.js +42 -42
- package/dist/lab/config.js +65 -25
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +8 -8
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +117 -57
- package/dist/lab/doctor.d.ts +10 -3
- package/dist/lab/doctor.js +47 -9
- package/dist/lab/init-templates.js +147 -147
- package/dist/lab/init.d.ts +1 -1
- package/dist/lab/init.js +41 -9
- package/dist/lab/keys.d.ts +2 -0
- package/dist/lab/keys.js +42 -8
- package/dist/lab/lab-deps.d.ts +7 -12
- package/dist/lab/parse/actors.js +9 -9
- package/dist/lab/parse/comms.js +5 -5
- package/dist/lab/parse/execution.js +13 -13
- package/dist/lab/parse/study-v3.d.ts +23 -0
- package/dist/lab/parse/study-v3.js +259 -0
- package/dist/lab/parse/subject-state.d.ts +7 -7
- package/dist/lab/parse/subject-state.js +16 -16
- package/dist/lab/parse/subject.js +28 -28
- package/dist/lab/parse/values.d.ts +1 -1
- package/dist/lab/parse/values.js +3 -3
- package/dist/lab/persona-resolve.d.ts +4 -4
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/plan-participants.d.ts +2 -2
- package/dist/lab/plan-types.d.ts +4 -4
- package/dist/lab/plan.d.ts +1 -7
- package/dist/lab/plan.js +10 -41
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -4
- package/dist/lab/preflight.d.ts +7 -5
- package/dist/lab/preflight.js +5 -5
- package/dist/lab/routing.d.ts +31 -25
- package/dist/lab/routing.js +60 -29
- package/dist/lab/run-lab-events.d.ts +0 -3
- package/dist/lab/run-lab-events.js +0 -6
- package/dist/lab/run-lab-homes.d.ts +22 -10
- package/dist/lab/run-lab-homes.js +5 -1
- package/dist/lab/run-lab-options.d.ts +1 -1
- package/dist/lab/run-lab-options.js +16 -13
- package/dist/lab/summary.d.ts +7 -6
- package/dist/lab/summary.js +10 -10
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +101 -95
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +13 -13
- package/dist/lab/validation.js +44 -42
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +61 -33
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +6 -6
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +1 -1
- package/dist/observer/library.js +4 -2
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +10 -5
- package/dist/observer/run-routes.d.ts +3 -3
- package/dist/observer/run-routes.js +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +15 -15
- package/dist/routes/computer-use/bundle.js +3 -3
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
- package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
- package/dist/routes/computer-use/external-comms.d.ts +1 -1
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +18 -18
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-flush.d.ts +1 -1
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +4 -2
- package/dist/routes/computer-use/live-phase.js +6 -6
- package/dist/routes/computer-use/local-vm.js +1 -1
- package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
- package/dist/routes/computer-use/participant-desktop.js +4 -4
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +9 -9
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +31 -13
- package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
- package/dist/routes/computer-use/participant-prompt.js +6 -6
- package/dist/routes/computer-use/participant-runs.d.ts +7 -7
- package/dist/routes/computer-use/participant-runs.js +13 -13
- package/dist/routes/computer-use/plan.js +22 -22
- package/dist/routes/computer-use/preflight.js +21 -21
- package/dist/routes/computer-use/rerun-selection.js +1 -1
- package/dist/routes/computer-use/result.js +11 -11
- package/dist/routes/computer-use/route.d.ts +2 -1
- package/dist/routes/computer-use/route.js +15 -14
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +31 -31
- package/dist/routes/computer-use/setup.d.ts +1 -1
- package/dist/routes/computer-use/setup.js +17 -18
- package/dist/routes/computer-use/single-bundle.d.ts +7 -7
- package/dist/routes/computer-use/single-bundle.js +28 -30
- package/dist/routes/computer-use/subject-projection.d.ts +1 -1
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +40 -42
- package/dist/routes/computer-use/types.js +10 -10
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -4
- package/dist/routes/scripted/bundle.d.ts +2 -2
- package/dist/routes/scripted/bundle.js +13 -12
- package/dist/routes/scripted/plan.d.ts +1 -1
- package/dist/routes/scripted/plan.js +9 -9
- package/dist/routes/scripted/result.js +5 -5
- package/dist/routes/scripted/route.js +5 -6
- package/dist/routes/scripted/scenario.js +2 -2
- package/dist/routes/scripted/setup.js +7 -7
- package/dist/routes/scripted/subject.js +1 -1
- package/dist/routes/scripted/surface-records.js +3 -3
- package/dist/routes/scripted/types.d.ts +3 -5
- package/dist/routes/scripted/types.js +1 -1
- package/dist/routes/shared-world/bundle-records.js +9 -8
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +40 -38
- package/dist/routes/shared-world/checkpoints.d.ts +1 -1
- package/dist/routes/shared-world/checkpoints.js +1 -1
- package/dist/routes/shared-world/comms.d.ts +5 -5
- package/dist/routes/shared-world/comms.js +14 -14
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +7 -6
- package/dist/routes/shared-world/participant-specs.js +31 -24
- package/dist/routes/shared-world/plan.js +7 -7
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.js +14 -13
- package/dist/routes/shared-world/result.js +20 -21
- package/dist/routes/shared-world/route.js +23 -22
- package/dist/routes/shared-world/setup.d.ts +3 -3
- package/dist/routes/shared-world/setup.js +4 -4
- package/dist/routes/shared-world/types.d.ts +30 -28
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +3 -3
- package/dist/routes/terminal/adapter.js +5 -5
- package/dist/routes/terminal/bundle.d.ts +3 -3
- package/dist/routes/terminal/bundle.js +22 -21
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +7 -7
- package/dist/routes/terminal/dry-run.js +4 -4
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/live-finish.js +3 -3
- package/dist/routes/terminal/live-sandbox.js +12 -13
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.js +11 -11
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.js +8 -8
- package/dist/routes/terminal/route.js +6 -7
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.js +8 -7
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +2 -2
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +26 -28
- package/dist/routes/terminal/types.js +3 -3
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +46 -46
- package/dist/run/bundle.js +2 -1
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.js +7 -1
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +18 -18
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +20 -13
- package/dist/run/projection.d.ts +14 -14
- package/dist/run/projection.js +15 -15
- package/dist/run/reclaim.js +2 -2
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +8 -6
- package/dist/run/run-index.js +15 -16
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +5 -4
- package/dist/run/run.js +1 -1
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +36 -35
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +6 -6
- package/dist/run/stats.d.ts +12 -6
- package/dist/run/stats.js +116 -58
- package/dist/run/status.d.ts +8 -29
- package/dist/run/status.js +5 -27
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +6 -6
- package/dist/run/study-provenance.d.ts +47 -0
- package/dist/run/study-provenance.js +63 -0
- package/dist/run/study-result.d.ts +16 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-lab.d.ts +7 -7
- package/dist/run-lab.js +1 -3
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +43 -0
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/subject/clone.d.ts +1 -1
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.js +1 -1
- package/dist/subject/local-tree.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +8 -9
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +5 -5
- package/dist/subject/steps.js +4 -4
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
- package/dist/substrates/e2b/desktop-browser.js +8 -8
- package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
- package/dist/substrates/e2b/desktop-cdp.js +8 -8
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
- package/dist/substrates/e2b/desktop-executor.js +1 -1
- package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
- package/dist/substrates/e2b/desktop-geometry.js +7 -7
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/sandbox.d.ts +1 -1
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +6 -6
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +16 -16
- package/dist/tui/contract.js +10 -10
- package/dist/tui/launch.d.ts +4 -4
- package/dist/tui/launch.js +18 -19
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +82 -82
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +92 -43
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +56 -87
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +61 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +5 -5
- package/docs/architecture/terminal-product-route.md +67 -107
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +2 -5
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +45 -44
- package/docs/contracts/schemas.md +421 -362
- package/docs/contracts/study-analysis.md +3 -3
- package/docs/contracts/study-costs.md +11 -7
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +60 -58
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- package/docs/roadmap/world-class-open-source-v0.md +0 -311
|
@@ -41,7 +41,7 @@ function fanoutParticipantView(args, spec, index) {
|
|
|
41
41
|
: (outcome?.skippedReason ??
|
|
42
42
|
session?.reason ??
|
|
43
43
|
outcome?.sessionError ??
|
|
44
|
-
"
|
|
44
|
+
"Dry run: the evidence shape was written without launching a desktop or spending provider tokens.");
|
|
45
45
|
const traceScreenshotMode = session?.trace.redaction.screenshots;
|
|
46
46
|
const screenshotMode = traceScreenshotMode === "raw" || traceScreenshotMode === "blurred"
|
|
47
47
|
? traceScreenshotMode
|
|
@@ -80,13 +80,12 @@ function fanoutParticipantRecord(args, spec, index, view) {
|
|
|
80
80
|
? `Participant ${spec.planned.id} ${outcome.skippedReason}.`
|
|
81
81
|
: outcome?.sessionError !== undefined
|
|
82
82
|
? `Participant ${spec.planned.id} failed before a terminal session verdict: ${outcome.sessionError}`
|
|
83
|
-
: `
|
|
83
|
+
: `Participant ${spec.planned.id} (${spec.persona.id}/${spec.planned.device.name}) for ${args.descriptor.id} against ${publicTargetUrl}; no session ran.`,
|
|
84
84
|
startedAt: args.run.createdAt,
|
|
85
85
|
updatedAt: args.run.createdAt,
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
function fanoutParticipantStream(args, spec, view) {
|
|
89
|
-
const { plan } = args;
|
|
90
89
|
const { outcome, publicTargetUrl, session, desktopGeometry, screenshots } = view;
|
|
91
90
|
const { lastScreenshot, status, reason, screenshotMode } = view;
|
|
92
91
|
const judged = outcome === undefined ? undefined : judgedStatus(participantFactsOf(outcome));
|
|
@@ -104,7 +103,7 @@ function fanoutParticipantStream(args, spec, view) {
|
|
|
104
103
|
? {}
|
|
105
104
|
: { caseGroup: spec.planned.labels.caseGroup }),
|
|
106
105
|
kind: "browser",
|
|
107
|
-
label:
|
|
106
|
+
label: `${spec.planned.id} · browser`,
|
|
108
107
|
status,
|
|
109
108
|
...(judged === undefined ? {} : { judgedStatus: judged }),
|
|
110
109
|
transport: "snapshot",
|
|
@@ -113,9 +112,9 @@ function fanoutParticipantStream(args, spec, view) {
|
|
|
113
112
|
? {
|
|
114
113
|
kind: "screenshot",
|
|
115
114
|
url: lastScreenshot,
|
|
116
|
-
title: `
|
|
115
|
+
title: `Desktop (${screenshotMode})`,
|
|
117
116
|
}
|
|
118
|
-
: { kind: "placeholder", title:
|
|
117
|
+
: { kind: "placeholder", title: "Desktop" },
|
|
119
118
|
...(desktopGeometry.viewport === undefined
|
|
120
119
|
? {}
|
|
121
120
|
: {
|
|
@@ -180,7 +179,7 @@ function fanoutSubjectEvents(ctx, spec, view) {
|
|
|
180
179
|
const { publicTargetUrl, subject, session } = view;
|
|
181
180
|
const events = [];
|
|
182
181
|
const record = (event) => events.push(participantEvent(spec, event));
|
|
183
|
-
// Per-participant subject provenance
|
|
182
|
+
// Per-participant subject provenance.
|
|
184
183
|
if (args.plan.runner.subject.kind === "clone" && args.publicRepo) {
|
|
185
184
|
record({
|
|
186
185
|
id: nextEventId(`subject-${spec.planned.id}`),
|
|
@@ -188,7 +187,7 @@ function fanoutSubjectEvents(ctx, spec, view) {
|
|
|
188
187
|
level: "info",
|
|
189
188
|
type: "cua-lab.subject.provenance",
|
|
190
189
|
message: `Participant ${spec.planned.id}: ${args.dryRun
|
|
191
|
-
? `subject declared: clone of ${args.publicRepo}, served at ${publicTargetUrl} in-sandbox (dry
|
|
190
|
+
? `subject declared: clone of ${args.publicRepo}, served at ${publicTargetUrl} in-sandbox (dry run; nothing cloned)`
|
|
192
191
|
: subject.commit
|
|
193
192
|
? session
|
|
194
193
|
? `subject cloned from ${args.publicRepo}@${subject.commit} and served at ${publicTargetUrl} in-sandbox`
|
|
@@ -203,7 +202,7 @@ function fanoutSubjectEvents(ctx, spec, view) {
|
|
|
203
202
|
level: "info",
|
|
204
203
|
type: "cua-lab.subject.provenance",
|
|
205
204
|
message: `Participant ${spec.planned.id}: ${args.dryRun
|
|
206
|
-
? `subject declared: local working tree, to be packed and served at ${publicTargetUrl} in-sandbox (dry
|
|
205
|
+
? `subject declared: local working tree, to be packed and served at ${publicTargetUrl} in-sandbox (dry run; nothing packed)`
|
|
207
206
|
: subject.archiveSha256
|
|
208
207
|
? session
|
|
209
208
|
? `subject packed (archiveSha256 ${subject.archiveSha256}${subject.dirty === true ? ", dirty working tree" : subject.dirty === false ? ", clean working tree" : ""}) and served at ${publicTargetUrl} in-sandbox`
|
|
@@ -270,7 +269,7 @@ function fanoutOutcomeEvents(ctx, spec, view) {
|
|
|
270
269
|
at: args.run.createdAt,
|
|
271
270
|
level: "info",
|
|
272
271
|
type: "cua-lab.contract.ready",
|
|
273
|
-
message: `Participant ${spec.planned.id}: dry-run
|
|
272
|
+
message: `Participant ${spec.planned.id}: dry-run participant ready; switch scenario.mode to live for a real desktop session.`,
|
|
274
273
|
});
|
|
275
274
|
}
|
|
276
275
|
for (const warning of desktopGeometry.warnings ?? []) {
|
|
@@ -282,7 +281,7 @@ function fanoutOutcomeEvents(ctx, spec, view) {
|
|
|
282
281
|
message: warning,
|
|
283
282
|
});
|
|
284
283
|
}
|
|
285
|
-
// Persisted per-participant phase trail (real boot timing): one RunEvent per
|
|
284
|
+
// Persisted per-participant phase trail (real boot timing): one RunEvent per completed phase
|
|
286
285
|
// boundary this participant recorded (started events never persist here; they carry no durationMs).
|
|
287
286
|
for (const phase of outcome?.phaseRecords ?? []) {
|
|
288
287
|
record({
|
|
@@ -12,7 +12,7 @@ export interface LiveTraceFlush {
|
|
|
12
12
|
stop: () => Promise<void>;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Incremental live flush
|
|
15
|
+
* Incremental live flush: as each participant's loop reports its recorded-so-far items,
|
|
16
16
|
* rewrite the in-progress bundle with per-stream `liveActor` partials so the attached
|
|
17
17
|
* Observer's 5s poll sees the timeline grow. Throttled (one write per interval, trailing
|
|
18
18
|
* write guaranteed). `write` is the run's `writeSnapshot`, which serializes writes and refuses
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { attachObserverRuntimeStreamUrls } from "../../observer/render.js";
|
|
2
2
|
import {} from "../../observer/run-routes.js";
|
|
3
3
|
/**
|
|
4
|
-
* Incremental live flush
|
|
4
|
+
* Incremental live flush: as each participant's loop reports its recorded-so-far items,
|
|
5
5
|
* rewrite the in-progress bundle with per-stream `liveActor` partials so the attached
|
|
6
6
|
* Observer's 5s poll sees the timeline grow. Throttled (one write per interval, trailing
|
|
7
7
|
* write guaranteed). `write` is the run's `writeSnapshot`, which serializes writes and refuses
|
|
@@ -42,9 +42,9 @@ export function startLiveTraceFlush(args) {
|
|
|
42
42
|
liveActor: {
|
|
43
43
|
schema: "humanish.live-actor.v1",
|
|
44
44
|
updatedAt,
|
|
45
|
-
//
|
|
46
|
-
// surface watching a live run can only name the participant id
|
|
47
|
-
//
|
|
45
|
+
// Who this participant is, carried while the run is live. Without it a
|
|
46
|
+
// surface watching a live run can only name the participant id and the stream
|
|
47
|
+
// label (`<participant id> · browser`), which describe the harness, not the participant.
|
|
48
48
|
...(personaByStream.get(stream.id) === undefined
|
|
49
49
|
? {}
|
|
50
50
|
: { persona: { id: personaByStream.get(stream.id) } }),
|
|
@@ -125,8 +125,8 @@ export function trackRuntimeStreams(onStream) {
|
|
|
125
125
|
await onStream?.(event);
|
|
126
126
|
if (event.type === "ready")
|
|
127
127
|
urls.push({ streamId: event.streamId, url: event.url });
|
|
128
|
-
// Mark, never remove: the tile needs to
|
|
129
|
-
// have the stream silently vanish from the overlay
|
|
128
|
+
// Mark, never remove: the tile needs to know the live view ended (and say so) rather than
|
|
129
|
+
// have the stream silently vanish from the overlay.
|
|
130
130
|
else
|
|
131
131
|
for (const entry of urls)
|
|
132
132
|
if (entry.streamId === event.streamId)
|
|
@@ -10,10 +10,12 @@ export declare function runLabParticipants(setup: CuaRunSetup, participants: Cua
|
|
|
10
10
|
result: {
|
|
11
11
|
automaticAnalysis?: import("../../analysis/job.js").AutomaticAnalysisOutcome;
|
|
12
12
|
automaticAnalysisTrigger?: "default" | "explicit";
|
|
13
|
-
schema: typeof import("
|
|
13
|
+
schema: typeof import("../../run/study-result.js").STUDY_RESULT_SCHEMA;
|
|
14
|
+
route: "computer-use";
|
|
15
|
+
studyId: string;
|
|
16
|
+
labId: string;
|
|
14
17
|
ok: boolean;
|
|
15
18
|
cwd: string;
|
|
16
|
-
labId: string;
|
|
17
19
|
actor: string;
|
|
18
20
|
appUrl: string;
|
|
19
21
|
dryRun: boolean;
|
|
@@ -20,10 +20,10 @@ export async function runLabParticipants(setup, participants) {
|
|
|
20
20
|
const inProcess = plan.runner.desktop === "in-process";
|
|
21
21
|
const subjectEnvNames = [...participantSubjectEnv(plan.runner.subject)];
|
|
22
22
|
const { runId, paths: runPaths } = run;
|
|
23
|
-
// A live run writes what it is doing
|
|
24
|
-
// This
|
|
25
|
-
// run launched by an agent (`lab run --json`), detached, or from the terminal surface
|
|
26
|
-
// nothing at all until it
|
|
23
|
+
// A live run writes what it is doing as it does it, whether or not anyone is currently watching.
|
|
24
|
+
// This is not gated on `options.onObserverReady` (the interactive Observer callback): gated, a
|
|
25
|
+
// run launched by an agent (`lab run --json`), detached, or from the terminal surface records
|
|
26
|
+
// nothing at all until it completes, and anything asking "what is this participant doing right
|
|
27
27
|
// now" got silence for the whole run. Who reads the evidence is not the run's business; the
|
|
28
28
|
// callback below stays conditional, the writing does not.
|
|
29
29
|
if (!dryRun) {
|
|
@@ -47,7 +47,7 @@ export async function runLabParticipants(setup, participants) {
|
|
|
47
47
|
streams.showIn(liveObserver);
|
|
48
48
|
if (input.onObserverReady)
|
|
49
49
|
await input.onObserverReady(liveObserver);
|
|
50
|
-
// Incremental live flush
|
|
50
|
+
// Incremental live flush: as each participant's loop reports its recorded-so-far items,
|
|
51
51
|
// rewrite the in-progress bundle with per-stream `liveActor` partials so the attached
|
|
52
52
|
// Observer's 5s poll sees the timeline grow. The run refuses any snapshot once the final
|
|
53
53
|
// write began; the route stops the flush timer on every exit below.
|
|
@@ -91,7 +91,7 @@ export async function runLabParticipants(setup, participants) {
|
|
|
91
91
|
return {
|
|
92
92
|
ok: false,
|
|
93
93
|
result: {
|
|
94
|
-
...fail("
|
|
94
|
+
...fail("HUMANISH_COMPUTER_USE_SUBJECT_INVALID", "Real email setup failed before desktop allocation. Run humanish comms check --online and humanish comms recover to inspect authentication and pending cleanup.", descriptor.id),
|
|
95
95
|
runId,
|
|
96
96
|
},
|
|
97
97
|
};
|
|
@@ -26,7 +26,7 @@ function guestAssets(options, account, needsMedia) {
|
|
|
26
26
|
if (account) {
|
|
27
27
|
const readiness = await checkRestrictedCodexAnalysisReadiness({ timeoutMs: 5000 });
|
|
28
28
|
if (!readiness.ready)
|
|
29
|
-
throw new Error(`Codex account is not ready (${readiness.errorCode}). Run humanish doctor --
|
|
29
|
+
throw new Error(`Codex account is not ready (${readiness.errorCode}). Run humanish doctor --study <study> before starting a local study.`);
|
|
30
30
|
}
|
|
31
31
|
return (options.assets ??
|
|
32
32
|
(await prepareLocalRuntime({
|
|
@@ -38,11 +38,11 @@ export interface ParticipantDesktop {
|
|
|
38
38
|
}
|
|
39
39
|
/** Builds one participant's desktop. The factory must not acquire anything; prepare does. */
|
|
40
40
|
export type ParticipantDesktopFactory = (run: DesktopParticipantRun, warnings: string[], artifactRoot: PreparedOutputRoot) => ParticipantDesktop;
|
|
41
|
-
/** The participant's addressed comms recipient, when one exists
|
|
42
|
-
* inbox instruction
|
|
41
|
+
/** The participant's addressed comms recipient, when one exists: the gate and the address source for the
|
|
42
|
+
* inbox instruction. A participant told to check an inbox it can never receive into would stall,
|
|
43
43
|
* so no addressed recipient means no instruction. */
|
|
44
44
|
export declare function inboxRecipientFor(commsEmail: LabCommsEmail, participantId: string): LabCommsRecipient | undefined;
|
|
45
|
-
/** True when a participant has a declared comms recipient
|
|
45
|
+
/** True when a participant has a declared comms recipient with an address, so the drain can actually match the
|
|
46
46
|
* mail the persona will be told to read. Gates the inbox instruction to participants that can receive
|
|
47
|
-
* mail
|
|
47
|
+
* mail; a participant told to check an inbox it can never receive into would just stall. */
|
|
48
48
|
export declare function participantHasInboxRecipient(commsEmail: LabCommsEmail, participantId: string): boolean;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { recipientParticipantId } from "../../lab/parse/comms.js";
|
|
2
|
-
/** The participant's addressed comms recipient, when one exists
|
|
3
|
-
* inbox instruction
|
|
2
|
+
/** The participant's addressed comms recipient, when one exists: the gate and the address source for the
|
|
3
|
+
* inbox instruction. A participant told to check an inbox it can never receive into would stall,
|
|
4
4
|
* so no addressed recipient means no instruction. */
|
|
5
5
|
export function inboxRecipientFor(commsEmail, participantId) {
|
|
6
6
|
return (commsEmail.recipients ?? []).find((recipient) => recipientParticipantId(recipient) === participantId && recipient.address !== undefined);
|
|
7
7
|
}
|
|
8
|
-
/** True when a participant has a declared comms recipient
|
|
8
|
+
/** True when a participant has a declared comms recipient with an address, so the drain can actually match the
|
|
9
9
|
* mail the persona will be told to read. Gates the inbox instruction to participants that can receive
|
|
10
|
-
* mail
|
|
10
|
+
* mail; a participant told to check an inbox it can never receive into would just stall. */
|
|
11
11
|
export function participantHasInboxRecipient(commsEmail, participantId) {
|
|
12
12
|
return inboxRecipientFor(commsEmail, participantId) !== undefined;
|
|
13
13
|
}
|
|
@@ -11,12 +11,12 @@ export declare function makeParticipantWriteScreenshot(artifactRoot: PreparedOut
|
|
|
11
11
|
export declare function runCuaParticipant(spec: DesktopParticipantRun, deps: CuaParticipantDeps): Promise<ParticipantRunOutcome>;
|
|
12
12
|
/**
|
|
13
13
|
* Run N>1 E2B participants with bounded concurrency, a pipeline gate (the first provisions
|
|
14
|
-
* before the rest start), and session fail-fast on
|
|
14
|
+
* before the rest start), and session fail-fast on harness errors only (queued participants
|
|
15
15
|
* become `blocked` with a pinned reason + a fail-fast event; mission verdicts never trip it).
|
|
16
|
-
* Each participant tears down
|
|
16
|
+
* Each participant tears down its own sandbox by id; nothing here ever enumerates.
|
|
17
17
|
*
|
|
18
|
-
* Exported for the
|
|
19
|
-
*
|
|
18
|
+
* Exported for the total-runner tests: the injectable runner lets a test make one participant
|
|
19
|
+
* throw (the exact class the guard exists for) without a live sandbox. Production always uses
|
|
20
20
|
* the default.
|
|
21
21
|
*/
|
|
22
22
|
export declare function runCuaParticipants(runs: DesktopParticipantRun[], deps: Omit<CuaParticipantDeps, "signalProvisioned">, concurrency: number, runParticipant?: typeof runCuaParticipant): Promise<{
|
|
@@ -132,12 +132,12 @@ export async function runCuaParticipant(spec, deps) {
|
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
134
134
|
* Run N>1 E2B participants with bounded concurrency, a pipeline gate (the first provisions
|
|
135
|
-
* before the rest start), and session fail-fast on
|
|
135
|
+
* before the rest start), and session fail-fast on harness errors only (queued participants
|
|
136
136
|
* become `blocked` with a pinned reason + a fail-fast event; mission verdicts never trip it).
|
|
137
|
-
* Each participant tears down
|
|
137
|
+
* Each participant tears down its own sandbox by id; nothing here ever enumerates.
|
|
138
138
|
*
|
|
139
|
-
* Exported for the
|
|
140
|
-
*
|
|
139
|
+
* Exported for the total-runner tests: the injectable runner lets a test make one participant
|
|
140
|
+
* throw (the exact class the guard exists for) without a live sandbox. Production always uses
|
|
141
141
|
* the default.
|
|
142
142
|
*/
|
|
143
143
|
export async function runCuaParticipants(runs, deps, concurrency, runParticipant = runCuaParticipant) {
|
|
@@ -164,10 +164,10 @@ export async function runCuaParticipants(runs, deps, concurrency, runParticipant
|
|
|
164
164
|
if (failFast.tripped) {
|
|
165
165
|
return skippedOutcome(spec, `skipped: ${failFast.reason}`);
|
|
166
166
|
}
|
|
167
|
-
// The participant runner is
|
|
167
|
+
// The participant runner is total: every exit path returns a recorded outcome. Without this
|
|
168
168
|
// guard, one participant's late throw (e.g. its trace write hitting ENOSPC after its own sandbox was
|
|
169
169
|
// already torn down) rejected the whole map while sibling workers kept launching sandboxes
|
|
170
|
-
// nobody would ever record
|
|
170
|
+
// nobody would ever record, so the run spent money and then reported nothing.
|
|
171
171
|
let outcome;
|
|
172
172
|
try {
|
|
173
173
|
outcome = await runParticipant(spec, {
|
|
@@ -187,7 +187,7 @@ export async function runCuaParticipants(runs, deps, concurrency, runParticipant
|
|
|
187
187
|
});
|
|
188
188
|
}
|
|
189
189
|
catch (error) {
|
|
190
|
-
// The first participant may have thrown before signaling the provisioning gate
|
|
190
|
+
// The first participant may have thrown before signaling the provisioning gate; release the followers as
|
|
191
191
|
// blocked rather than leaving them awaiting a gate that will never settle.
|
|
192
192
|
if (index === 0)
|
|
193
193
|
rejectGate?.();
|
|
@@ -247,7 +247,7 @@ export function toParticipantResult(spec, outcome, subject, dryRun) {
|
|
|
247
247
|
ok: false,
|
|
248
248
|
diagnostics: cuaParticipantDiagnostics({ dryRun, skipped: true }),
|
|
249
249
|
skippedReason: outcome.skippedReason,
|
|
250
|
-
error: { code: "
|
|
250
|
+
error: { code: "HUMANISH_COMPUTER_USE_FAILED", message: outcome.skippedReason },
|
|
251
251
|
};
|
|
252
252
|
}
|
|
253
253
|
const session = outcome.session;
|
|
@@ -299,7 +299,7 @@ export function toParticipantResult(spec, outcome, subject, dryRun) {
|
|
|
299
299
|
? {}
|
|
300
300
|
: {
|
|
301
301
|
error: {
|
|
302
|
-
code: outcome.failureCode ?? "
|
|
302
|
+
code: outcome.failureCode ?? "HUMANISH_COMPUTER_USE_FAILED",
|
|
303
303
|
message: outcome.sessionError ??
|
|
304
304
|
(outcome.noEngagement
|
|
305
305
|
? "Actor took no actions and produced no message (likely a blank/still-loading screen); not a credible goal_satisfied."
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CuaExecutor, CuaLoopResult, CuaProvider } from "../../actors/computer-use/loop.js";
|
|
2
|
+
import type { ActorConversation } from "../../actors/contract.js";
|
|
2
3
|
import type { CuaActorSessionOptions } from "../../actors/computer-use/actor.js";
|
|
3
4
|
import { startClaudeSession } from "../../actors/local-agent/claude-session.js";
|
|
4
5
|
import { createRestrictedCodexParticipant, type ParticipantProviderCloseResult } from "../../actors/codex/restricted-participant.js";
|
|
@@ -29,6 +30,11 @@ export declare function closeParticipantModel(model: ParticipantModel, warnings:
|
|
|
29
30
|
}>;
|
|
30
31
|
/** Prices the finished session's tokens onto its trace, writes the trace, and warns on raw screenshots. */
|
|
31
32
|
export declare function recordParticipantTrace(spec: DesktopParticipantRun, deps: ParticipantModelDeps, session: CuaLoopResult, warnings: string[]): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* The run warning for a participant whose provider kept no conversation server-side, so humanish
|
|
35
|
+
* carried it on every request. It says why, and how many early turns became a text summary.
|
|
36
|
+
*/
|
|
37
|
+
export declare function explicitContextWarning(conversation: ActorConversation): string;
|
|
32
38
|
/** The checks that keep a goal_satisfied session from counting as a pass, with their warnings. */
|
|
33
39
|
export declare function judgeParticipantSession(session: CuaLoopResult | undefined, deps: ParticipantModelDeps, warnings: string[]): {
|
|
34
40
|
noEngagement: boolean;
|
|
@@ -49,10 +49,10 @@ export async function startParticipantModel(spec, deps, executor) {
|
|
|
49
49
|
return { provider: codexParticipant.provider, codexParticipant };
|
|
50
50
|
}
|
|
51
51
|
if (localAgent === "claude") {
|
|
52
|
-
// One session for the whole run, like the codex thread above
|
|
52
|
+
// One session for the whole run, like the codex thread above. The one-shot
|
|
53
53
|
// provider (createLocalAgentProvider) spawned `claude -p` per turn, and every turn
|
|
54
54
|
// started with no memory of the last. HUMANISH_LOCAL_AGENT_ONE_SHOT=1 keeps that path
|
|
55
|
-
// reachable as a
|
|
55
|
+
// reachable as a measurement switch: MemTrapBench (2026-08) reports memory frameworks
|
|
56
56
|
// degrading agent performance by 10-40% on some tasks, so "remembers" has to be measured
|
|
57
57
|
// against "does not" on the same lab, not assumed. The trace records which one ran.
|
|
58
58
|
const oneShot = env.HUMANISH_LOCAL_AGENT_ONE_SHOT !== undefined &&
|
|
@@ -82,7 +82,7 @@ export async function startParticipantModel(spec, deps, executor) {
|
|
|
82
82
|
/** The options the participant's session runs with: prompt, model settings, spend caps and callbacks. */
|
|
83
83
|
export function participantSessionOptions(spec, deps, ready, provider, writeScreenshot) {
|
|
84
84
|
const { executor, inbox } = ready;
|
|
85
|
-
// The
|
|
85
|
+
// The fail-closed spend cap (execution.caps.maxUsd) is wired into the loop as maxUsd + an
|
|
86
86
|
// injected pure per-turn estimator keyed on the resolved model. Preflight already refused a
|
|
87
87
|
// cap on an unpriced model, so the estimate is measurable whenever a cap is in force. The
|
|
88
88
|
// model id here matches provider.version (openai-responses-cu resolves the default when unset).
|
|
@@ -95,7 +95,7 @@ export function participantSessionOptions(spec, deps, ready, provider, writeScre
|
|
|
95
95
|
persona: spec.persona,
|
|
96
96
|
timeoutMs: deps.timeoutMs,
|
|
97
97
|
// The brain is either a keyed API client or a CLI the operator is already signed in to.
|
|
98
|
-
// Everything below this line
|
|
98
|
+
// Everything below this line (loop, executor, trace, affordances) is identical either
|
|
99
99
|
// way, which is what makes a local-agent run comparable to an API one.
|
|
100
100
|
...(provider === undefined ? {} : { provider: provider }),
|
|
101
101
|
openai: {
|
|
@@ -129,8 +129,8 @@ export function participantSessionOptions(spec, deps, ready, provider, writeScre
|
|
|
129
129
|
: { stopWhen: spec.planned.limits.stopWhen }),
|
|
130
130
|
...(spec.planned.limits.dwell === undefined ? {} : { dwell: spec.planned.limits.dwell }),
|
|
131
131
|
...(spec.planned.tasks === undefined ? {} : { tasks: spec.planned.tasks }),
|
|
132
|
-
// The
|
|
133
|
-
// ledger and stops when the
|
|
132
|
+
// The study budget: this participant notes its own running estimate on the shared
|
|
133
|
+
// ledger and stops when the run total crosses the cap, independent of the per-participant
|
|
134
134
|
// maxUsd above.
|
|
135
135
|
...(deps.runBudget === undefined
|
|
136
136
|
? {}
|
|
@@ -149,8 +149,8 @@ export function participantSessionOptions(spec, deps, ready, provider, writeScre
|
|
|
149
149
|
...(deps.onTrace === undefined
|
|
150
150
|
? {}
|
|
151
151
|
: {
|
|
152
|
-
// Forwards the
|
|
153
|
-
// without it never reaches the flush
|
|
152
|
+
// Forwards the running usage as well: the participant runner is where both are known, and usage
|
|
153
|
+
// without it never reaches the flush, which is how the live cost stayed unknown.
|
|
154
154
|
onTrace: (items, usage, metadata) => deps.onTrace?.(spec.planned.id, items, usage, metadata),
|
|
155
155
|
}),
|
|
156
156
|
};
|
|
@@ -207,27 +207,45 @@ export async function closeParticipantModel(model, warnings) {
|
|
|
207
207
|
}
|
|
208
208
|
/** Prices the finished session's tokens onto its trace, writes the trace, and warns on raw screenshots. */
|
|
209
209
|
export async function recordParticipantTrace(spec, deps, session, warnings) {
|
|
210
|
-
// Per-participant model-token cost
|
|
211
|
-
// id is authoritative here
|
|
210
|
+
// Per-participant model-token cost estimate, attached to the trace before it is persisted (the model
|
|
211
|
+
// id is authoritative here: provider.version). Kept at the lab boundary so the pure loop
|
|
212
212
|
// never depends on the operator rate table. estimateActorCost declares absent (null) for an
|
|
213
213
|
// unknown rate / missing usage rather than guessing.
|
|
214
214
|
session.trace.estimatedCost = estimateActorCostForExecution(session.trace.tokenUsage, session.trace.ids.model, session.trace.executionProfile);
|
|
215
215
|
await writeContainedOutputFile(deps.artifactRoot, spec.traceArtifactPath, `${JSON.stringify(session.trace, null, 2)}\n`, "utf8");
|
|
216
|
+
const conversation = session.trace.conversation;
|
|
217
|
+
if (conversation?.mode === "explicit_context")
|
|
218
|
+
warnings.push(explicitContextWarning(conversation));
|
|
216
219
|
if (session.trace.redaction.screenshots === "raw") {
|
|
217
|
-
warnings.push("Screenshots are
|
|
220
|
+
warnings.push("Screenshots are unblurred for local use: the bundle stays in the gitignored .humanish/ folder and nothing scans these pixels, so review them before sharing. Set policies.redactScreenshots: true to blur screenshots in a bundle you plan to share.");
|
|
218
221
|
}
|
|
219
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* The run warning for a participant whose provider kept no conversation server-side, so humanish
|
|
225
|
+
* carried it on every request. It says why, and how many early turns became a text summary.
|
|
226
|
+
*/
|
|
227
|
+
export function explicitContextWarning(conversation) {
|
|
228
|
+
const why = conversation.explicitReason === "zdr_rejection"
|
|
229
|
+
? `The OpenAI organization rejected server-side conversation state (zero data retention)${conversation.switchedAtRequest === undefined
|
|
230
|
+
? ""
|
|
231
|
+
: ` on request ${conversation.switchedAtRequest}`}`
|
|
232
|
+
: "zeroDataRetention is set";
|
|
233
|
+
const summarized = conversation.summarizedTurns === 0
|
|
234
|
+
? ""
|
|
235
|
+
: ` To stay within its token budget it summarized the ${conversation.summarizedTurns} oldest turns as text and dropped their screenshots.`;
|
|
236
|
+
return `${why}, so humanish carried this participant's conversation itself (explicit_context).${summarized} The trace's conversation record has each request's carried context.`;
|
|
237
|
+
}
|
|
220
238
|
/** The checks that keep a goal_satisfied session from counting as a pass, with their warnings. */
|
|
221
239
|
export function judgeParticipantSession(session, deps, warnings) {
|
|
222
240
|
const noEngagement = session !== undefined && hollowCompletion(sessionEnding(session));
|
|
223
241
|
if (noEngagement) {
|
|
224
|
-
warnings.push("
|
|
242
|
+
warnings.push("The participant returned goal_satisfied with no actions and no messages, so it likely saw a blank or loading screen and stopped. This does not count as a pass. Check the screenshot, and raise execution.timeoutMs or confirm the app had rendered before the first turn.");
|
|
225
243
|
}
|
|
226
244
|
const blockerReason = resolveSelfReportedBlocker(session);
|
|
227
245
|
const selfReportedBlocker = blockerReason !== undefined;
|
|
228
246
|
const reportedFriction = resolveSelfReportedFriction(session) !== undefined;
|
|
229
247
|
if (selfReportedBlocker) {
|
|
230
|
-
warnings.push(`
|
|
248
|
+
warnings.push(`The participant returned goal_satisfied, but its final message describes a blocker or asks for missing instructions, so this does not count as a pass: ${redactText(deps.scrubKnownValues(blockerReason))}`);
|
|
231
249
|
}
|
|
232
250
|
return { noEngagement, selfReportedBlocker, reportedFriction };
|
|
233
251
|
}
|
|
@@ -5,7 +5,7 @@ import { type LabTask } from "../../lab/tasks.js";
|
|
|
5
5
|
import type { DesktopParticipantRun } from "./types.js";
|
|
6
6
|
export declare const DEFAULT_MISSION = "You are testing a web application. The browser is already open at the subject URL. Explore it, accomplish what the scenario asks, and stop when done.";
|
|
7
7
|
/**
|
|
8
|
-
* The participant's outcome as
|
|
8
|
+
* The participant's outcome as one fixed first line of its last message. The
|
|
9
9
|
* free-text computer-use provider has no schema to fill; a fixed line is the next best thing, and
|
|
10
10
|
* the loop reads it into the trace's declaredOutcome. Prompt-only control is weak in general, so
|
|
11
11
|
* adherence is measured (declaredOutcome present or absent on the trace) and the regex over the
|
|
@@ -21,24 +21,24 @@ export declare function composeParticipantInstructions(args: {
|
|
|
21
21
|
mission: string;
|
|
22
22
|
persona?: string;
|
|
23
23
|
instruction?: string;
|
|
24
|
-
/** The lab's declared protocol
|
|
24
|
+
/** The lab's declared protocol. Only the participant-facing `goal` halves are rendered
|
|
25
25
|
* into the prompt; the `success` criteria never appear here. */
|
|
26
26
|
tasks?: readonly LabTask[];
|
|
27
27
|
device: {
|
|
28
28
|
name: string;
|
|
29
29
|
preset: DevicePreset;
|
|
30
30
|
};
|
|
31
|
-
/** The
|
|
32
|
-
* makes the persona shape behavior
|
|
33
|
-
* traitsApplied
|
|
34
|
-
* no committed file, unparseable YAML) keeps the
|
|
31
|
+
/** The compiled persona for `args.persona`, when its committed file resolved. Supplying it
|
|
32
|
+
* makes the persona shape behavior: its traits become directives in the prompt and land in
|
|
33
|
+
* traitsApplied, instead of appearing as a bare `Persona: <id>.` label. Absent (unsafe id,
|
|
34
|
+
* no committed file, unparseable YAML) keeps the fallback: the bare line and an empty
|
|
35
35
|
* traitsApplied, never fabricated traits. Resolved by the caller so this stays pure. */
|
|
36
36
|
resolvedPersona?: ResolvedPersona;
|
|
37
37
|
/**
|
|
38
|
-
* desktop-cli
|
|
39
|
-
* because a participant whose every prior world was a browser will look for one
|
|
38
|
+
* desktop-cli: the surface under study is a terminal window, not a page. Said plainly
|
|
39
|
+
* because a participant whose every prior world was a browser will look for one, and because a
|
|
40
40
|
* capability nobody declares is one the recording cannot later be read against. It states that a
|
|
41
|
-
* terminal is open and
|
|
41
|
+
* terminal is open and does not say what to type in it: naming commands would answer the question the
|
|
42
42
|
* study is asking.
|
|
43
43
|
*/
|
|
44
44
|
surface?: "desktop-cli";
|
|
@@ -46,8 +46,8 @@ export declare function composeParticipantInstructions(args: {
|
|
|
46
46
|
instructions: string;
|
|
47
47
|
persona: ActorPersonaRef;
|
|
48
48
|
};
|
|
49
|
-
/** Runtime-inject the persona inbox instruction into a participant's prompt
|
|
50
|
-
* runtime loopback/getHost address (not secret), so
|
|
49
|
+
/** Runtime-inject the persona inbox instruction into a participant's prompt. The inbox URL is a
|
|
50
|
+
* runtime loopback/getHost address (not secret), so, mirroring the lobby-code runtime injection, this
|
|
51
51
|
* augments only the instructions the model receives; the authored prompt + its digest are unchanged.
|
|
52
52
|
* Returns a new spec (never mutates). Shared by the CUA + concurrent shared-world routes. */
|
|
53
53
|
export declare function withInboxMission(spec: DesktopParticipantRun, inboxUrl: string, address?: string, receiving?: boolean): DesktopParticipantRun;
|
|
@@ -7,7 +7,7 @@ import { personaBrief, personaToDirectives, renderPersonaPromptSection, } from "
|
|
|
7
7
|
import { renderTaskPrompt } from "../../lab/tasks.js";
|
|
8
8
|
export const DEFAULT_MISSION = "You are testing a web application. The browser is already open at the subject URL. Explore it, accomplish what the scenario asks, and stop when done.";
|
|
9
9
|
/**
|
|
10
|
-
* The participant's outcome as
|
|
10
|
+
* The participant's outcome as one fixed first line of its last message. The
|
|
11
11
|
* free-text computer-use provider has no schema to fill; a fixed line is the next best thing, and
|
|
12
12
|
* the loop reads it into the trace's declaredOutcome. Prompt-only control is weak in general, so
|
|
13
13
|
* adherence is measured (declaredOutcome present or absent on the trace) and the regex over the
|
|
@@ -26,12 +26,12 @@ export function composeParticipantInstructions(args) {
|
|
|
26
26
|
const deviceLine = preset.isMobile
|
|
27
27
|
? `You are a mobile user on a ${name} device (${preset.width}x${preset.height} @${preset.deviceScaleFactor}x). Expect a mobile/touch layout.`
|
|
28
28
|
: `You are a desktop user (${name}, ${preset.width}x${preset.height}).`;
|
|
29
|
-
// The protocol as the
|
|
30
|
-
// are the researcher's instrument and must never reach this prompt
|
|
29
|
+
// The protocol as the participant reads it: numbered goals, nothing else. The success criteria
|
|
30
|
+
// are the researcher's instrument and must never reach this prompt: a persona told how it will
|
|
31
31
|
// be measured optimizes for the measurement instead of using the product (src/lab/tasks.ts).
|
|
32
32
|
const taskLines = renderTaskPrompt(args.tasks ?? []);
|
|
33
33
|
// A resolved persona contributes its compiled directives (friction tolerance, skill bias,
|
|
34
|
-
// accessibility behavior, constraints) through the
|
|
34
|
+
// accessibility behavior, constraints) through the same persona.ts compiler the terminal route
|
|
35
35
|
// uses, so one persona file means one behavior across every route.
|
|
36
36
|
const personaLine = args.resolvedPersona
|
|
37
37
|
? renderPersonaPromptSection(args.resolvedPersona)
|
|
@@ -64,8 +64,8 @@ export function composeParticipantInstructions(args) {
|
|
|
64
64
|
},
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
|
-
/** Runtime-inject the persona inbox instruction into a participant's prompt
|
|
68
|
-
* runtime loopback/getHost address (not secret), so
|
|
67
|
+
/** Runtime-inject the persona inbox instruction into a participant's prompt. The inbox URL is a
|
|
68
|
+
* runtime loopback/getHost address (not secret), so, mirroring the lobby-code runtime injection, this
|
|
69
69
|
* augments only the instructions the model receives; the authored prompt + its digest are unchanged.
|
|
70
70
|
* Returns a new spec (never mutates). Shared by the CUA + concurrent shared-world routes. */
|
|
71
71
|
export function withInboxMission(spec, inboxUrl, address, receiving = false) {
|
|
@@ -13,17 +13,17 @@ export declare function defaultSessionTimeoutMs(config: LabConfig): number;
|
|
|
13
13
|
* costs the same wall-clock room either way. */
|
|
14
14
|
export declare function resolveParticipantSandboxMs(config: LabConfig): number;
|
|
15
15
|
/**
|
|
16
|
-
* The in-flight participant bound a lab declares. Defaults to the participant count
|
|
16
|
+
* The in-flight participant bound a lab declares. Defaults to the participant count: every
|
|
17
17
|
* declared participant runs at once, because a throttle nobody asked for silently turns "N actors
|
|
18
|
-
* live" into waves
|
|
19
|
-
* and simultaneity differ. A declared execution.concurrency is a
|
|
18
|
+
* live" into waves; total session count and spend are the same either way, only wall-clock
|
|
19
|
+
* and simultaneity differ. A declared execution.concurrency is a cap, clamped to [1, participants].
|
|
20
20
|
* The planner records it; the route may only lower it from the environment.
|
|
21
21
|
*/
|
|
22
22
|
export declare function boundedConcurrency(declared: number | undefined, participantCount: number): number;
|
|
23
23
|
/**
|
|
24
|
-
* Pure pre-flight plan resolver (runs in dry-run
|
|
24
|
+
* Pure pre-flight plan resolver (runs in dry-run and live). Returns the participant table, the
|
|
25
25
|
* effective concurrency, the wave count, the per-participant session budget, and the worst-case total
|
|
26
|
-
* sandbox-minutes
|
|
26
|
+
* sandbox-minutes, before any sandbox or provider call. The same plan appears in dry-run,
|
|
27
27
|
* marked $0 (dryRun: true).
|
|
28
28
|
*/
|
|
29
29
|
export declare function resolveCuaParticipantPlan(config: LabConfig, opts?: {
|
|
@@ -32,8 +32,8 @@ export declare function resolveCuaParticipantPlan(config: LabConfig, opts?: {
|
|
|
32
32
|
dryRun?: boolean;
|
|
33
33
|
personas?: Map<string, ResolvedPersona>;
|
|
34
34
|
}): CuaParticipantPlan;
|
|
35
|
-
/** Print the participant plan to stderr
|
|
36
|
-
* digests, and budgets only
|
|
35
|
+
/** Print the participant plan to stderr before any sandbox/provider call (public-safe: ids, devices,
|
|
36
|
+
* digests, and budgets only; no prompt text, no secrets). */
|
|
37
37
|
export declare function emitPreflightPlan(participantPlan: CuaParticipantPlan, labId: string): void;
|
|
38
38
|
export declare function formatParticipantPlanEntry(entry: CuaParticipantPlanEntry): string;
|
|
39
39
|
/**
|