humanish 0.107.0 → 0.109.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 +73 -69
- package/CHANGELOG.md +27 -0
- package/CONTEXT.md +51 -44
- package/README.md +148 -175
- 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-trace.js +2 -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 +20 -18
- 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 +3 -3
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +18 -18
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/admission-limit.d.ts +3 -3
- package/dist/actors/computer-use/admission-limit.js +4 -4
- package/dist/actors/computer-use/executor-error.d.ts +2 -2
- package/dist/actors/computer-use/executor-error.js +3 -3
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +15 -15
- 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/debrief.js +2 -2
- package/dist/actors/computer-use/loop/ending.d.ts +6 -6
- package/dist/actors/computer-use/loop/ending.js +18 -17
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +15 -14
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +12 -12
- package/dist/actors/computer-use/loop/session.d.ts +4 -4
- package/dist/actors/computer-use/loop/session.js +4 -4
- 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 +11 -9
- package/dist/actors/computer-use/loop/types.d.ts +47 -45
- package/dist/actors/computer-use/loop/usage.d.ts +2 -2
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/loop.d.ts +6 -1
- package/dist/actors/computer-use/loop.js +26 -4
- 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 +13 -10
- package/dist/actors/computer-use/openai-provider.js +52 -41
- 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/computer-use/provider-error.d.ts +4 -4
- package/dist/actors/computer-use/provider-error.js +6 -6
- package/dist/actors/contract.d.ts +82 -47
- package/dist/actors/contract.js +30 -24
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +13 -12
- package/dist/actors/local-agent/cli.d.ts +9 -7
- 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 +8 -8
- package/dist/actors/registry.d.ts +12 -12
- package/dist/actors/registry.js +21 -20
- package/dist/actors/scripted-browser/actor.d.ts +10 -10
- package/dist/actors/scripted-browser/actor.js +17 -17
- 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/automatic-completion.d.ts +7 -7
- package/dist/analysis/automatic-completion.js +1 -1
- package/dist/analysis/automatic-config.d.ts +6 -6
- package/dist/analysis/automatic-config.js +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/execute.d.ts +1 -1
- package/dist/analysis/execute.js +1 -1
- package/dist/analysis/service.js +5 -5
- package/dist/analysis/types.d.ts +6 -0
- package/dist/browser-control/client.js +16 -16
- package/dist/browser-control/dispatcher.js +4 -4
- package/dist/browser-control/protocol.js +14 -14
- package/dist/browser-control/recording-transfer.js +4 -4
- package/dist/browser-control/transport.js +7 -7
- package/dist/cli/commands/analysis-signals.d.ts +2 -2
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +48 -35
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.d.ts +0 -1
- package/dist/cli/commands/observe.js +136 -112
- 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 +136 -139
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +27 -24
- package/dist/cli/commands/study-format.d.ts +9 -0
- package/dist/cli/commands/{lab-format.js → study-format.js} +39 -27
- package/dist/cli/commands/{lab-route-computer-use.d.ts → study-route-computer-use.d.ts} +6 -6
- package/dist/cli/commands/{lab-route-computer-use.js → study-route-computer-use.js} +17 -18
- package/dist/cli/commands/{lab-route-open.d.ts → study-route-open.d.ts} +4 -4
- package/dist/cli/commands/{lab-route-open.js → study-route-open.js} +2 -2
- package/dist/cli/commands/{lab-route-preview.d.ts → study-route-preview.d.ts} +7 -7
- package/dist/cli/commands/{lab-route-preview.js → study-route-preview.js} +7 -6
- package/dist/cli/commands/study-route-run.d.ts +19 -0
- package/dist/cli/commands/{lab-route-run.js → study-route-run.js} +6 -6
- package/dist/cli/commands/study-route-scripted.d.ts +17 -0
- package/dist/cli/commands/{lab-route-scripted.js → study-route-scripted.js} +4 -4
- package/dist/cli/commands/{lab-route-shared-world.d.ts → study-route-shared-world.d.ts} +5 -5
- package/dist/cli/commands/{lab-route-shared-world.js → study-route-shared-world.js} +10 -10
- package/dist/cli/commands/study-route-terminal.d.ts +17 -0
- package/dist/cli/commands/{lab-route-terminal.js → study-route-terminal.js} +4 -4
- package/dist/cli/commands/study-run.d.ts +9 -0
- package/dist/cli/commands/{lab-run.js → study-run.js} +44 -45
- package/dist/cli/commands/{lab-scorer.d.ts → study-scorer.d.ts} +7 -7
- package/dist/cli/commands/{lab-scorer.js → study-scorer.js} +2 -2
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +146 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +31 -31
- package/dist/cli/commands/watch.js +71 -121
- package/dist/cli/deprecations.d.ts +6 -0
- package/dist/cli/deprecations.js +18 -0
- package/dist/cli/doctor.d.ts +18 -8
- package/dist/cli/doctor.js +114 -59
- package/dist/cli/first-run-path.d.ts +15 -13
- package/dist/cli/first-run-path.js +35 -33
- package/dist/cli/io.d.ts +44 -9
- package/dist/cli/io.js +98 -23
- package/dist/cli/observer-follow.d.ts +3 -3
- package/dist/cli/observer-follow.js +6 -7
- package/dist/cli/orientation.d.ts +10 -7
- package/dist/cli/orientation.js +89 -47
- 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 +111 -43
- package/dist/cli/telemetry.d.ts +16 -16
- package/dist/cli/telemetry.js +46 -44
- 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 +17 -17
- package/dist/comms/connections.d.ts +1 -1
- package/dist/comms/connections.js +2 -2
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.d.ts +5 -5
- package/dist/comms/external-evidence.js +5 -4
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +3 -3
- package/dist/comms/fake-inbox.js +3 -3
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/receiving-runtime.d.ts +4 -4
- 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 +38 -39
- package/dist/comms/sandbox-catch.js +36 -37
- package/dist/comms/setup.d.ts +2 -2
- package/dist/comms/setup.js +56 -25
- 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 +38 -80
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +10 -10
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/feedback/proof.d.ts +1 -1
- package/dist/feedback/proof.js +2 -2
- package/dist/guest/bootstrap.js +6 -6
- package/dist/guest/browser-tools.js +8 -8
- package/dist/guest/chromium-text.js +19 -19
- package/dist/guest/desktop-executor.d.ts +2 -2
- package/dist/guest/desktop-executor.js +20 -20
- package/dist/guest/desktop-keys.js +4 -4
- package/dist/guest/desktop-media.d.ts +2 -2
- package/dist/guest/desktop-media.js +16 -16
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/desktop-native.js +10 -10
- package/dist/guest/runtime-desktop.js +2 -2
- package/dist/guest/runtime-processes.d.ts +2 -2
- package/dist/guest/runtime-processes.js +2 -2
- package/dist/guest/runtime.js +6 -6
- package/dist/index.d.ts +14 -14
- package/dist/index.js +8 -8
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/observer/artifact.d.ts +2 -2
- package/dist/observer/artifact.js +7 -7
- 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 +3 -1
- package/dist/observer/library.js +8 -3
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +17 -6
- package/dist/observer/run-routes.d.ts +4 -3
- package/dist/observer/run-routes.js +38 -13
- package/dist/observer/serve.d.ts +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 +18 -17
- package/dist/routes/computer-use/bundle.d.ts +2 -2
- package/dist/routes/computer-use/bundle.js +10 -9
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +6 -6
- package/dist/routes/computer-use/e2b-desktop/comms.js +18 -17
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/prepare.js +10 -10
- package/dist/routes/computer-use/e2b-desktop/start.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/teardown.js +2 -2
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +27 -26
- package/dist/routes/computer-use/fanout-records.js +12 -13
- package/dist/routes/computer-use/live-flush.d.ts +4 -4
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +5 -4
- package/dist/routes/computer-use/live-phase.js +8 -8
- package/dist/routes/computer-use/local-tree-pack.d.ts +5 -5
- package/dist/routes/computer-use/local-tree-pack.js +1 -1
- package/dist/routes/computer-use/local-vm.d.ts +8 -8
- package/dist/routes/computer-use/local-vm.js +3 -3
- package/dist/routes/computer-use/participant-desktop.d.ts +7 -7
- package/dist/routes/computer-use/participant-desktop.js +5 -5
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +10 -10
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +33 -15
- package/dist/routes/computer-use/participant-prompt.d.ts +15 -15
- package/dist/routes/computer-use/participant-prompt.js +9 -9
- package/dist/routes/computer-use/participant-runs.d.ts +16 -16
- package/dist/routes/computer-use/participant-runs.js +26 -25
- package/dist/routes/computer-use/plan.d.ts +12 -12
- package/dist/routes/computer-use/plan.js +42 -42
- package/dist/routes/computer-use/preflight.d.ts +5 -5
- package/dist/routes/computer-use/preflight.js +25 -25
- package/dist/routes/computer-use/rerun-selection.d.ts +1 -1
- package/dist/routes/computer-use/rerun-selection.js +4 -3
- package/dist/routes/computer-use/result.d.ts +4 -4
- package/dist/routes/computer-use/result.js +22 -21
- package/dist/routes/computer-use/route.d.ts +12 -11
- package/dist/routes/computer-use/route.js +31 -30
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +32 -32
- package/dist/routes/computer-use/setup.d.ts +23 -23
- package/dist/routes/computer-use/setup.js +28 -29
- package/dist/routes/computer-use/single-bundle.d.ts +11 -11
- package/dist/routes/computer-use/single-bundle.js +40 -41
- package/dist/routes/computer-use/subject-projection.d.ts +4 -4
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +71 -73
- package/dist/routes/computer-use/types.js +12 -12
- package/dist/routes/preview.d.ts +13 -7
- package/dist/routes/preview.js +11 -7
- package/dist/routes/scripted/bundle.d.ts +7 -7
- package/dist/routes/scripted/bundle.js +20 -18
- package/dist/routes/scripted/plan.d.ts +8 -8
- package/dist/routes/scripted/plan.js +13 -13
- package/dist/routes/scripted/result.d.ts +3 -3
- package/dist/routes/scripted/result.js +13 -13
- package/dist/routes/scripted/route.d.ts +9 -9
- package/dist/routes/scripted/route.js +15 -16
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +5 -5
- package/dist/routes/scripted/setup.d.ts +6 -6
- package/dist/routes/scripted/setup.js +8 -8
- package/dist/routes/scripted/subject.d.ts +5 -5
- package/dist/routes/scripted/subject.js +4 -4
- package/dist/routes/scripted/surface-records.d.ts +1 -1
- package/dist/routes/scripted/surface-records.js +4 -4
- package/dist/routes/scripted/surface-sessions.d.ts +3 -3
- package/dist/routes/scripted/types.d.ts +18 -20
- package/dist/routes/scripted/types.js +2 -2
- package/dist/routes/shared-world/bundle-records.js +11 -10
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +46 -43
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +2 -2
- package/dist/routes/shared-world/comms.d.ts +14 -14
- package/dist/routes/shared-world/comms.js +19 -18
- 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 +10 -9
- package/dist/routes/shared-world/participant-specs.js +38 -31
- package/dist/routes/shared-world/plan.d.ts +9 -9
- package/dist/routes/shared-world/plan.js +16 -16
- 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.d.ts +8 -8
- package/dist/routes/shared-world/provisioned.js +18 -17
- package/dist/routes/shared-world/result.d.ts +6 -6
- package/dist/routes/shared-world/result.js +29 -29
- package/dist/routes/shared-world/route.d.ts +11 -11
- package/dist/routes/shared-world/route.js +40 -39
- package/dist/routes/shared-world/setup.d.ts +16 -16
- package/dist/routes/shared-world/setup.js +23 -23
- package/dist/routes/shared-world/types.d.ts +55 -53
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +5 -5
- package/dist/routes/terminal/adapter.js +9 -9
- package/dist/routes/terminal/bundle.d.ts +13 -13
- package/dist/routes/terminal/bundle.js +28 -27
- package/dist/routes/terminal/credentials.d.ts +8 -8
- package/dist/routes/terminal/credentials.js +12 -12
- package/dist/routes/terminal/dry-run.d.ts +4 -4
- package/dist/routes/terminal/dry-run.js +12 -12
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +5 -5
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/lifetime.d.ts +1 -1
- package/dist/routes/terminal/lifetime.js +1 -1
- package/dist/routes/terminal/live-finish.d.ts +2 -2
- package/dist/routes/terminal/live-finish.js +10 -10
- package/dist/routes/terminal/live-sandbox.d.ts +2 -2
- package/dist/routes/terminal/live-sandbox.js +15 -15
- package/dist/routes/terminal/participant-text.js +2 -1
- package/dist/routes/terminal/persona.d.ts +2 -2
- package/dist/routes/terminal/persona.js +3 -3
- package/dist/routes/terminal/plan.d.ts +7 -7
- package/dist/routes/terminal/plan.js +15 -15
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.d.ts +5 -5
- package/dist/routes/terminal/result.js +14 -14
- package/dist/routes/terminal/route.d.ts +9 -9
- package/dist/routes/terminal/route.js +19 -20
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.d.ts +5 -5
- package/dist/routes/terminal/session.js +14 -13
- 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 +4 -4
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +48 -50
- package/dist/routes/terminal/types.js +5 -5
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +49 -49
- package/dist/run/bundle.js +3 -2
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.d.ts +23 -0
- package/dist/run/costs.js +79 -44
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.d.ts +1 -1
- package/dist/run/dry-run-inputs.js +2 -2
- package/dist/run/dry-run.js +20 -20
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/outcomes.d.ts +1 -1
- package/dist/run/participant.d.ts +1 -1
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/preflight-receipts.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +22 -15
- package/dist/run/projection.d.ts +46 -46
- package/dist/run/projection.js +57 -57
- package/dist/run/reclaim.d.ts +1 -1
- package/dist/run/reclaim.js +3 -3
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-cost.d.ts +53 -0
- package/dist/run/run-cost.js +105 -0
- package/dist/run/run-index-analysis.d.ts +15 -0
- package/dist/run/run-index-analysis.js +77 -0
- package/dist/run/run-index.d.ts +19 -7
- package/dist/run/run-index.js +77 -64
- 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 +6 -5
- package/dist/run/run.js +3 -3
- 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 +37 -36
- 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 +7 -7
- package/dist/run/stats.d.ts +14 -8
- package/dist/run/stats.js +121 -63
- package/dist/run/status.d.ts +16 -29
- package/dist/run/status.js +10 -29
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +7 -7
- package/dist/run/study-provenance.d.ts +49 -0
- package/dist/run/study-provenance.js +66 -0
- package/dist/run/study-result.d.ts +11 -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-study.d.ts +112 -0
- package/dist/{run-lab.js → run-study.js} +52 -47
- package/dist/{lab → study}/adapter-extension.d.ts +15 -27
- package/dist/{lab → study}/adapter-extension.js +10 -45
- package/dist/{lab → study}/adapter-scorer-loader.d.ts +17 -17
- package/dist/{lab → study}/adapter-scorer-loader.js +34 -34
- package/dist/study/composition-rules.d.ts +7 -0
- package/dist/{lab → study}/composition-rules.js +53 -53
- package/dist/study/config.d.ts +15 -0
- package/dist/{lab → study}/config.js +98 -41
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/{lab → study}/device-presets.d.ts +10 -10
- package/dist/{lab → study}/device-presets.js +11 -11
- package/dist/study/discover.d.ts +75 -0
- package/dist/{lab → study}/discover.js +134 -95
- package/dist/{lab → study}/doctor.d.ts +19 -12
- package/dist/{lab → study}/doctor.js +58 -20
- 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 +44 -0
- package/dist/{lab → study}/init-templates.d.ts +2 -2
- package/dist/study/init-templates.js +421 -0
- package/dist/{lab → study}/init.d.ts +2 -2
- package/dist/{lab → study}/init.js +46 -11
- package/dist/study/keys.d.ts +4 -0
- package/dist/{lab → study}/keys.js +46 -12
- 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/{lab → study}/parse/actors.d.ts +5 -5
- package/dist/{lab → study}/parse/actors.js +14 -14
- package/dist/study/parse/comms.d.ts +12 -0
- package/dist/{lab → study}/parse/comms.js +5 -5
- package/dist/study/parse/execution.d.ts +19 -0
- package/dist/{lab → study}/parse/execution.js +13 -13
- package/dist/study/parse/study-v3.d.ts +21 -0
- package/dist/study/parse/study-v3.js +259 -0
- package/dist/study/parse/subject-state.d.ts +30 -0
- package/dist/{lab → study}/parse/subject-state.js +19 -19
- package/dist/{lab → study}/parse/subject.d.ts +3 -3
- package/dist/{lab → study}/parse/subject.js +34 -34
- package/dist/{lab → study}/parse/values.d.ts +3 -3
- package/dist/{lab → study}/parse/values.js +3 -3
- package/dist/{lab → study}/persona-resolve.d.ts +8 -8
- package/dist/{lab → study}/persona-resolve.js +6 -6
- package/dist/{lab → study}/plan-base.d.ts +7 -7
- package/dist/{lab → study}/plan-base.js +1 -1
- package/dist/{lab → study}/plan-participants.d.ts +12 -12
- package/dist/{lab → study}/plan-participants.js +4 -4
- package/dist/{lab → study}/plan-types.d.ts +31 -31
- package/dist/{lab → study}/plan-types.js +2 -2
- package/dist/study/plan.d.ts +13 -0
- package/dist/study/plan.js +101 -0
- package/dist/study/preflight-probes.d.ts +3 -0
- package/dist/{lab → study}/preflight-probes.js +20 -19
- package/dist/study/preflight-result.d.ts +8 -0
- package/dist/{lab → study}/preflight-result.js +5 -4
- package/dist/study/preflight.d.ts +94 -0
- package/dist/{lab → study}/preflight.js +12 -12
- package/dist/{lab → study}/requirements.d.ts +3 -3
- package/dist/{lab → study}/requirements.js +1 -1
- package/dist/study/route-inputs.d.ts +28 -0
- package/dist/{lab → study}/route-inputs.js +1 -1
- package/dist/{lab → study}/routing.d.ts +39 -33
- package/dist/{lab → study}/routing.js +60 -29
- package/dist/{lab/run-lab-events.d.ts → study/run-study-events.d.ts} +10 -13
- package/dist/{lab/run-lab-events.js → study/run-study-events.js} +3 -9
- package/dist/{lab/run-lab-homes.d.ts → study/run-study-homes.d.ts} +21 -18
- package/dist/{lab/run-lab-homes.js → study/run-study-homes.js} +1 -1
- package/dist/study/run-study-options.d.ts +28 -0
- package/dist/{lab/run-lab-options.js → study/run-study-options.js} +29 -25
- package/dist/{lab/lab-deps.d.ts → study/study-deps.d.ts} +8 -13
- package/dist/{lab/lab-deps.js → study/study-deps.js} +2 -2
- package/dist/{lab → study}/summary.d.ts +16 -15
- package/dist/{lab → study}/summary.js +21 -21
- package/dist/{lab → study}/tasks.d.ts +18 -18
- package/dist/{lab → study}/tasks.js +14 -14
- package/dist/{lab → study}/types.d.ts +202 -196
- package/dist/{lab → study}/types.js +3 -1
- package/dist/{lab → study}/validation.d.ts +27 -27
- package/dist/{lab → study}/validation.js +53 -51
- package/dist/study/warnings.d.ts +12 -0
- package/dist/{lab → study}/warnings.js +62 -34
- package/dist/subject/clone.d.ts +7 -7
- package/dist/subject/clone.js +2 -2
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.d.ts +2 -2
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +4 -4
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +9 -10
- package/dist/subject/serve.d.ts +5 -5
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +4 -4
- package/dist/subject/state.js +1 -1
- package/dist/subject/steps.d.ts +6 -6
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/desktop-session.js +2 -2
- 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 +6 -6
- package/dist/substrates/e2b/desktop-browser.js +9 -9
- package/dist/substrates/e2b/desktop-cdp.d.ts +10 -10
- package/dist/substrates/e2b/desktop-cdp.js +9 -9
- package/dist/substrates/e2b/desktop-executor.d.ts +2 -2
- package/dist/substrates/e2b/desktop-executor.js +13 -13
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +8 -8
- package/dist/substrates/e2b/desktop-media.d.ts +4 -4
- 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/lifetime.js +1 -1
- package/dist/substrates/e2b/sandbox.d.ts +4 -4
- package/dist/substrates/e2b/sandbox.js +2 -2
- package/dist/substrates/e2b/sdk.d.ts +12 -12
- package/dist/substrates/e2b/sdk.js +7 -7
- package/dist/substrates/local/runtime-config.d.ts +4 -4
- package/dist/substrates/local/runtime-config.js +4 -4
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +23 -23
- package/dist/tui/contract.js +11 -11
- package/dist/tui/launch.d.ts +7 -7
- package/dist/tui/launch.js +36 -31
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +139 -139
- 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 +5 -5
- package/dist/verify/subject.js +19 -19
- package/dist/verify/verify.js +94 -44
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +60 -91
- package/docs/architecture/browser-control.md +1 -1
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +68 -65
- package/docs/architecture/github-feedback-loop.md +2 -5
- 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 +6 -6
- package/docs/architecture/terminal-product-route.md +70 -110
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +4 -7
- 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 +42 -44
- package/docs/contracts/schemas.md +446 -368
- package/docs/contracts/study-analysis.md +7 -4
- package/docs/contracts/study-costs.md +28 -9
- 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/README.md +1 -1
- 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/examples/scorer/scorer.mjs +3 -3
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +64 -60
- 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-format.d.ts +0 -8
- package/dist/cli/commands/lab-route-run.d.ts +0 -19
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -17
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -17
- package/dist/cli/commands/lab-run.d.ts +0 -9
- 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/lab/composition-rules.d.ts +0 -7
- package/dist/lab/config.d.ts +0 -7
- package/dist/lab/discover.d.ts +0 -65
- package/dist/lab/init-templates.js +0 -416
- package/dist/lab/keys.d.ts +0 -2
- package/dist/lab/parse/comms.d.ts +0 -12
- package/dist/lab/parse/execution.d.ts +0 -19
- package/dist/lab/parse/subject-state.d.ts +0 -30
- package/dist/lab/plan.d.ts +0 -19
- package/dist/lab/plan.js +0 -132
- package/dist/lab/preflight-probes.d.ts +0 -3
- package/dist/lab/preflight-result.d.ts +0 -7
- package/dist/lab/preflight.d.ts +0 -92
- package/dist/lab/route-inputs.d.ts +0 -28
- package/dist/lab/run-lab-options.d.ts +0 -28
- package/dist/lab/warnings.d.ts +0 -2
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/dist/run-lab.d.ts +0 -112
- 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
- /package/dist/{lab → study}/init-paths.d.ts +0 -0
- /package/dist/{lab → study}/init-paths.js +0 -0
- /package/dist/{lab → study}/init-plan.d.ts +0 -0
- /package/dist/{lab → study}/init-plan.js +0 -0
- /package/dist/{lab → study}/participant-assignment.d.ts +0 -0
- /package/dist/{lab → study}/participant-assignment.js +0 -0
- /package/dist/{lab → study}/persona.d.ts +0 -0
- /package/dist/{lab → study}/persona.js +0 -0
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
# Contract Schema Index
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
|
-
marked "reserved" name layering intent only; no code emits or validates them
|
|
9
|
-
yet. Do not emit a reserved schema.
|
|
3
|
+
This page maps the shipped contracts; it does not list every command or result envelope. The
|
|
4
|
+
exported types, schema constants, parsers and validators in `src/` are the source of truth. A row
|
|
5
|
+
marked "reserved" names layering intent only: no code emits or validates it yet, so do not emit a
|
|
6
|
+
reserved schema.
|
|
10
7
|
|
|
11
8
|
## Purpose
|
|
12
9
|
|
|
@@ -31,7 +28,7 @@ workflow without leaking private upstream truth into core.
|
|
|
31
28
|
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
|
|
32
29
|
| Run bundle | `humanish.run-bundle.v1` | `synthetic-run-bundle` |
|
|
33
30
|
| Adapter | `humanish.adapter.v1` | `synthetic-cli-adapter` |
|
|
34
|
-
|
|
|
31
|
+
| Study file | `humanish.study.v3` | `first-run` |
|
|
35
32
|
| Persona | `humanish.persona.v1` | `synthetic-maintainer` |
|
|
36
33
|
| Scenario | `humanish.scenario.v1` | `first-run-smoke` |
|
|
37
34
|
| Actor trace | `humanish.actor-trace.v1` | `synthetic-actor-trace` |
|
|
@@ -55,32 +52,73 @@ workflow without leaking private upstream truth into core.
|
|
|
55
52
|
| Adapter score | `humanish.adapter-score.v1` (`RunBundle.adapterScore`; namespaced; route-specific acceptance semantics) | see Product-Adapter Extension Seam below |
|
|
56
53
|
| Adapter artifact | `humanish.adapter-artifact.v1` (`RunBundle.adapterArtifacts[]`; namespaced; local relative proof references) | see Product-Adapter Extension Seam below |
|
|
57
54
|
| Shared-world evidence | `humanish.shared-world.v1` (additive `RunBundle.sharedWorld` + `RunBundle.attributionClass`; `topologyMode: sequential \| concurrent`) | see Shared-World Evidence below |
|
|
58
|
-
| Comms thread | `humanish.comms-thread.v1` (off-app email/SMS the app sent, captured; a `kind: log` run-dir artifact of
|
|
55
|
+
| Comms thread | `humanish.comms-thread.v1` (off-app email/SMS the app sent, captured; a `kind: log` run-dir artifact of digests only: from/to/subject/link digests + one OTP count, never raw) | see `comms` under Study File |
|
|
59
56
|
| Serve result | `humanish.serve-result.v1` (`src/observer/serve.ts` is authoritative) | none (command result envelope; see Serve Result below) |
|
|
60
57
|
| Serve control plane | reserved (`/_humanish/api/*` answers `501` `HUMANISH_SERVE_CONTROL_PLANE_DISABLED` in v1) | none |
|
|
61
58
|
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
Schema: `humanish.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
## Study File
|
|
60
|
+
|
|
61
|
+
Schema: `humanish.study.v3`. `src/study/parse/study-v3.ts` rewrites a v3 document into the
|
|
62
|
+
normalized config in `src/study/types.ts`, which `src/study/config.ts` parses. humanish refuses a
|
|
63
|
+
`humanish.lab.v2` file with `HUMANISH_STUDY_V2_UNSUPPORTED`, whose message names
|
|
64
|
+
`humanish migrate <path>`; migrate converts the file to v3.
|
|
65
|
+
|
|
66
|
+
A study declares its route and composes code primitives; it is not a hardcoded kind. The
|
|
67
|
+
top-level keys:
|
|
68
|
+
|
|
69
|
+
| Key | Meaning |
|
|
70
|
+
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `schema`, `id`, `title`, `description` | the document's identity |
|
|
72
|
+
| `route` | required: `preview`, `computer-use`, `shared-world`, `terminal` or `scripted` |
|
|
73
|
+
| `mode` | `dry-run` (the default) or `live` |
|
|
74
|
+
| `actor` | who drives it, one object: `type`, `model`, `localAgent`, `persona`, `mission`, `tasks`, `maxOutputTokens`, `reasoningEffort`, `stopWhen`, `dwell` |
|
|
75
|
+
| `participants` | a count, a homogeneous `{ count, instruction }`, or a list of entries (below) |
|
|
76
|
+
| `surfaces` | scripted only: `[desktop]` or `[desktop, mobile]` |
|
|
77
|
+
| `caps` | the route's budget (below) |
|
|
78
|
+
| `scenario` | scripted only: a committed scenario id or path |
|
|
79
|
+
| `subject`, `execution`, `policies`, `review`, `defaults`, `comms` | as below |
|
|
80
|
+
|
|
81
|
+
The parser reads only the declared route's keys. A key that route never reads is an error that
|
|
82
|
+
names the route, such as "route: computer-use does not read scenario. Remove it.", and an
|
|
83
|
+
unknown key is an error that lists the known ones; both are `HUMANISH_STUDY_INVALID`.
|
|
84
|
+
|
|
85
|
+
`participants` takes the forms its route accepts:
|
|
86
|
+
|
|
87
|
+
| Route | Forms | Default |
|
|
88
|
+
| -------------- | ------------------------------------------------------------------------------ | -------------- |
|
|
89
|
+
| `preview` | a count | 4 |
|
|
90
|
+
| `computer-use` | a count, a homogeneous object, or a list (a `local-app` subject takes no list) | 1 |
|
|
91
|
+
| `shared-world` | a list of at least two entries | none: required |
|
|
92
|
+
| `scripted` | none; `surfaces` instead | |
|
|
93
|
+
| `terminal` | none; one agent | |
|
|
94
|
+
|
|
95
|
+
`caps` keeps each route's meaning, and a route refuses the keys it does not read:
|
|
96
|
+
`computer-use` and `shared-world` read `maxUsd` and `maxTotalUsd`; `terminal` reads `maxUsd`,
|
|
97
|
+
`maxJobs` and `maxMinutes`; `preview` and `scripted` take no `caps`.
|
|
98
|
+
|
|
99
|
+
`humanish migrate` maps a v2 file as follows: `actors[0]` is `actor`; `lanes` is the `participants` list; a
|
|
100
|
+
`roster` group is an entry with `count`; `count` is the count; `count` with `laneFocus` is the
|
|
101
|
+
homogeneous object; `execution.caps` (computer-use, shared-world) or `scenario.caps`
|
|
102
|
+
(terminal) is `caps`; `scenario.mode` is `mode`; `scenario.ref` is `scenario`; and
|
|
103
|
+
`subject.topology: shared-world` is `route: shared-world`. A key the v2 inert-field table
|
|
104
|
+
marks inert for the route is not in v3.
|
|
105
|
+
|
|
106
|
+
The rest of this section names keys by their v3 spelling:
|
|
69
107
|
|
|
70
108
|
- `subject`: what the run acts on: `this-repo`, `clone` (owner/repo slugs,
|
|
71
109
|
optional in-sandbox `serve` + env var names + `state`), `local-tree` (the
|
|
72
110
|
operator's own working tree, packed on the host and provisioned in-sandbox
|
|
73
111
|
in place of a clone; see below), `app-url`
|
|
74
112
|
(loopback unless `policies.allowPublicTargets` declares an owned deployment),
|
|
75
|
-
`local-app` (an already-running
|
|
76
|
-
custom `
|
|
113
|
+
`local-app` (an already-running local dev server driven in-process via a
|
|
114
|
+
custom `ComputerUseExecutor`, no clone and no E2B desktop, always loopback),
|
|
77
115
|
`terminal-product` (a CLI/product a real autonomous terminal agent studies
|
|
78
|
-
from
|
|
116
|
+
from public surfaces only; see below), or `desktop-cli` (a computer-use
|
|
79
117
|
participant using a CLI in a terminal on a hosted desktop). A
|
|
80
118
|
`local-app` subject pairs a computer-use actor with `execution.target: local`
|
|
81
119
|
(or absent) and is library-assisted: the caller supplies
|
|
82
|
-
`
|
|
83
|
-
closed (`
|
|
120
|
+
`RunStudyOptions.inProcess.executor` + `createProvider`; with neither the engine fails
|
|
121
|
+
closed (`HUMANISH_COMPUTER_USE_LOCAL_APP_NO_EXECUTOR`), never a desktop attempt. See
|
|
84
122
|
[`docs/architecture/state-driven-executor.md`](../architecture/state-driven-executor.md);
|
|
85
123
|
- `subject.localTree` (`local-tree` subjects, computer-use route): pack/upload
|
|
86
124
|
knobs for the packed working tree: `exclude[]` (extra archive excludes on
|
|
@@ -93,8 +131,8 @@ A lab is a composition over code primitives, not a hardcoded kind:
|
|
|
93
131
|
`maxArchiveBytes` (upload size cap override; default 256 MiB). Routing requires `execution.target: e2b-desktop` and a
|
|
94
132
|
computer-use actor; `subject.serve`/`env`/`state` apply exactly as they do
|
|
95
133
|
on the clone route (identical install/build/start/state semantics). The
|
|
96
|
-
packed root is the
|
|
97
|
-
(an absolute path in a
|
|
134
|
+
packed root is the study resolution cwd; there is no path field, by design
|
|
135
|
+
(an absolute path in a study file would be a machine-specific,
|
|
98
136
|
unshareable, leak-prone artifact). Enumeration is git-aware when the root
|
|
99
137
|
is a git work tree (`git ls-files --cached --others --exclude-standard`,
|
|
100
138
|
honoring `.gitignore`) or a denylist-only recursive walk otherwise; an
|
|
@@ -104,17 +142,17 @@ A lab is a composition over code primitives, not a hardcoded kind:
|
|
|
104
142
|
`src/subject/local-tree-archive.ts`)
|
|
105
143
|
applies in both modes and is not overridable. The denylist matches names,
|
|
106
144
|
not contents; a secret in a file it does not name packs like any other
|
|
107
|
-
file, so review the pack summary line and use `localTree.exclude`. The
|
|
108
|
-
|
|
145
|
+
file, so review the pack summary line and use `localTree.exclude`. The study packs
|
|
146
|
+
once per run and uploads the identical archive to every fan-out participant. The
|
|
109
147
|
in-sandbox commit refresh clone subjects use is skipped: `.git` is never
|
|
110
148
|
uploaded, so identity comes from the host-side archive digest instead. See
|
|
111
|
-
[`docs/goals/local-tree-subject/goal.md`](https://github.com/danielgwilson/humanish/blob/main/docs/goals/local-tree-subject/goal.md);
|
|
149
|
+
[`docs/history/goals/local-tree-subject/goal.md`](https://github.com/danielgwilson/humanish/blob/main/docs/history/goals/local-tree-subject/goal.md);
|
|
112
150
|
- `subject.product` (terminal-product subjects): the product the agent studies.
|
|
113
|
-
`product.name` is a public-safe token (committed fixtures use a
|
|
151
|
+
`product.name` is a public-safe token (committed fixtures use a neutral mock
|
|
114
152
|
name); `product.publicSurfaces[]` is the list of http(s) URLs (docs, llms.txt,
|
|
115
|
-
skill manifest) that are the
|
|
116
|
-
clone/provision the product, so its provenance is recorded
|
|
117
|
-
|
|
153
|
+
skill manifest) that are the only world the agent sees. The study does not
|
|
154
|
+
clone/provision the product, so its provenance is recorded
|
|
155
|
+
unpinned. `serve`/`clone`/`state`/`repos`/`appUrl` are rejected on a
|
|
118
156
|
terminal-product subject (a field that cannot act on the route is a parse
|
|
119
157
|
error, not silently dropped). See
|
|
120
158
|
[`docs/architecture/terminal-product-route.md`](../architecture/terminal-product-route.md);
|
|
@@ -122,83 +160,80 @@ A lab is a composition over code primitives, not a hardcoded kind:
|
|
|
122
160
|
subject's state story. `state.seed[]` declares ordered, bounded
|
|
123
161
|
seed/migration/fixture steps (`{ name, command, when: before-build |
|
|
124
162
|
before-start | after-ready, timeoutMs }`) executed in-sandbox around the
|
|
125
|
-
serve sequence; `state.external[]` declares env var
|
|
126
|
-
appear in `subject.env`) pointing at state the
|
|
127
|
-
recorded as
|
|
163
|
+
serve sequence; `state.external[]` declares env var names (each must also
|
|
164
|
+
appear in `subject.env`) pointing at state the study does not control,
|
|
165
|
+
recorded as unpinned in provenance. Commands persist in evidence as
|
|
128
166
|
sha256-16 digests only, never as text;
|
|
129
|
-
- `
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
167
|
+
- `actor`: who drives it. On the computer-use, shared-world, scripted and
|
|
168
|
+
terminal routes, `actor.type` is a real dispatch key resolved against the
|
|
169
|
+
actor registry. On the preview route it remains a descriptive label (e.g.
|
|
170
|
+
`synthetic-persona`). The
|
|
133
171
|
`codex-exec` descriptor's direct `runSession` member is a fail-closed
|
|
134
|
-
compatibility entry, not the live runner; the terminal
|
|
172
|
+
compatibility entry, not the live runner; the terminal route
|
|
135
173
|
owns the live sandbox, auth, cap, evidence, and cleanup lifecycle.
|
|
136
|
-
`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
participant (no E2B to fan out);
|
|
142
|
-
- `
|
|
143
|
-
each `{ id?, actorType?, surface?, caseGroup?, persona?, device?,
|
|
174
|
+
A `participants` count is the preview route's participant count (simCount),
|
|
175
|
+
and on the computer-use **E2B** route the homogeneous fan-out count (N
|
|
176
|
+
identical participants, each its own E2B desktop: separate worlds, cap 16).
|
|
177
|
+
The scripted route's `surfaces` is its surface list (`[desktop]`, the default,
|
|
178
|
+
or `[desktop, mobile]`). The in-process/local-app computer-use route stays
|
|
179
|
+
single participant (no E2B to fan out);
|
|
180
|
+
- a `participants` list (computer-use E2B route): a differentiated fan-out,
|
|
181
|
+
each entry `{ id?, actorType?, surface?, caseGroup?, persona?, device?,
|
|
144
182
|
instruction?, target?, entry?, host?, reasoningEffort?, stopWhen?, dwell? }` becoming one independent E2B desktop (or, on the
|
|
145
183
|
shared-world routes, one participant against the shared plane). `actorType`,
|
|
146
184
|
`surface`, and `caseGroup` are adapter-owned public-safe labels for grouping
|
|
147
185
|
simulated users; they are not core enums, and `actorType` is deliberately
|
|
148
|
-
separate from the execution dispatch key `
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
`lanes[].device` is XOR with a raw `execution.desktop.resolution`. Participant ids
|
|
186
|
+
separate from the execution dispatch key `actor.type`. A list sets the count,
|
|
187
|
+
so `--count` does not apply to it, and each entry's `instruction` is the steer;
|
|
188
|
+
an entry's `device` is XOR with a raw `execution.desktop.resolution`. Participant ids
|
|
152
189
|
default `lane-01`..`lane-NN` (`role-01`..`role-NN` for shared-world participants), must be unique, and name per-participant evidence paths
|
|
153
|
-
(`actors/<streamId>.json`, `screenshots/<laneId>/`). Cap 16 participants.
|
|
154
|
-
routes
|
|
155
|
-
|
|
156
|
-
`
|
|
157
|
-
- `
|
|
190
|
+
(`actors/<streamId>.json`, `screenshots/<laneId>/`). Cap 16 participants. The other
|
|
191
|
+
routes refuse a list (table above). `subject.clone.fanout` is rejected on the
|
|
192
|
+
computer-use, shared-world and scripted routes (declare fan-out with
|
|
193
|
+
`participants`). No current route reads `clone.fanout`;
|
|
194
|
+
- `participants[].target` (app-url × computer-use E2B route only): an
|
|
158
195
|
absolute browser URL that participant opens instead of `subject.appUrl`. This is the
|
|
159
|
-
setup-produced-target handoff for crawler/swarm
|
|
196
|
+
setup-produced-target handoff for crawler/swarm studies: an adapter may start any
|
|
160
197
|
topology it needs, then declare exactly which target each actor should drive.
|
|
161
|
-
If any participant declares `target`, every
|
|
198
|
+
If any participant declares `target`, every entry in the list must declare one.
|
|
162
199
|
Public/non-loopback targets still require `policies.allowPublicTargets: true`.
|
|
163
200
|
`target` is mutually exclusive with `entry`: `target` is an absolute app-url
|
|
164
201
|
browser target; `entry` is a shared-world participant's same-origin path;
|
|
165
|
-
- `
|
|
166
|
-
repeated
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...), so the runtime and run bundle keep one normalized participant shape. `roster`
|
|
171
|
-
is XOR with explicit `lanes`, homogeneous `count`, and `laneFocus`;
|
|
202
|
+
- a `participants` entry with `count: n` (computer-use E2B route): a group of
|
|
203
|
+
repeated participants. It needs an `id` and the parser expands it to
|
|
204
|
+
`<id>-01` … `<id>-NN`, even when n is 1, before the engine runs (`viewer-01`,
|
|
205
|
+
`viewer-02`, ...), so the runtime and run bundle keep one normalized participant
|
|
206
|
+
shape. Ids are checked for collisions after expansion;
|
|
172
207
|
- `execution.concurrency` (computer-use E2B routes, including shared-world): a
|
|
173
|
-
|
|
208
|
+
cap on participants in flight at once. When omitted, every participant runs
|
|
174
209
|
simultaneously: independent participants resolve it from the final participant count,
|
|
175
210
|
after any `--count` override, and the parser fills `concurrency = participantCount`
|
|
176
|
-
for multi-participant shared-world
|
|
211
|
+
for multi-participant shared-world studies. Total sessions and spend are identical either way; only wall-clock
|
|
177
212
|
and simultaneity differ. Declaring a value below the participant count runs participants in
|
|
178
213
|
waves and emits a warning saying so, because a green waved run is otherwise
|
|
179
|
-
indistinguishable from the all-live run the author meant. Shared-world
|
|
214
|
+
indistinguishable from the all-live run the author meant. Shared-world studies
|
|
180
215
|
need at least 2 (the host and a follower are live together); `concurrency: 1`
|
|
181
216
|
there is refused at parse, since the sequential turn-taking route was removed
|
|
182
217
|
in 0.106.0. The env override
|
|
183
|
-
`HUMANISH_CUA_MAX_CONCURRENCY` may only
|
|
184
|
-
raise concurrent paid desktops
|
|
218
|
+
`HUMANISH_CUA_MAX_CONCURRENCY` may only lower the effective bound, never
|
|
219
|
+
raise concurrent paid desktops, and a lowering is recorded on
|
|
185
220
|
the plan (`envLoweredConcurrencyFrom`). Inert (warned) on other routes.
|
|
186
|
-
`execution.timeoutMs` is the
|
|
221
|
+
`execution.timeoutMs` is the per-participant session budget on this route (semantics
|
|
187
222
|
change: it was the single-session budget pre-fan-out); there is no run-level
|
|
188
223
|
wall clock. `policies.allowPublicTargets` cannot combine with N>1 against one
|
|
189
224
|
implicit public `subject.appUrl` (ambiguous shared-world-ish topology); it may
|
|
190
|
-
combine with N>1 only when
|
|
191
|
-
|
|
192
|
-
routes N>1 against one public target to the
|
|
225
|
+
combine with N>1 only when every `participants` entry declares `target`, or when
|
|
226
|
+
the study declares `route: shared-world`. That
|
|
227
|
+
routes N>1 against one public target to the external-public shared-world plane
|
|
193
228
|
(see Shared-World Evidence below), not separate worlds;
|
|
194
229
|
- `subject.publicTarget: { owner, authorized: true }` (external-public shared-world
|
|
195
|
-
route
|
|
196
|
-
deployment (`source: app-url` + `
|
|
230
|
+
route only): the operator's required ownership attestation when a real public
|
|
231
|
+
deployment (`source: app-url` + `route: shared-world` + `allowPublicTargets` +
|
|
197
232
|
`concurrency > 1`) is used directly as the shared plane. The harness neither
|
|
198
233
|
provisions nor exposes the target, so it cannot attest synthetic data; the operator
|
|
199
|
-
|
|
200
|
-
subjects and inert (warned) on other app-url routes. `
|
|
201
|
-
- `subject.appUrl`: a loopback http(s) URL a computer-use actor drives,
|
|
234
|
+
must attest they own/operate it. Author-trust (unverifiable); rejected on non-app-url
|
|
235
|
+
subjects and inert (warned) on other app-url routes. `participants[].host: true` marks the single designated host participant there;
|
|
236
|
+
- `subject.appUrl`: a loopback http(s) URL a computer-use actor drives, or (on the
|
|
202
237
|
external-public shared-world route) the non-loopback public deployment used as the
|
|
203
238
|
shared plane (with `publicTarget` + `allowPublicTargets`);
|
|
204
239
|
- `execution`: where it runs (`local`, `e2b-desktop`, or `e2b-terminal`), plus
|
|
@@ -210,18 +245,18 @@ dwell? }`. The parser expands it into
|
|
|
210
245
|
computer-use and scripted-browser routes refuse it when a library caller skips
|
|
211
246
|
the parser;
|
|
212
247
|
- `execution.desktop.template` (e2b-desktop computer-use and clone scripted-browser routes): a custom E2B
|
|
213
|
-
desktop
|
|
248
|
+
desktop template (image) name or ID the run launches on, for a subject that
|
|
214
249
|
needs runtimes the stock `desktop` image lacks (e.g. node/bun/a local Postgres
|
|
215
250
|
baked into an adopter-maintained image). Any non-empty string is a valid
|
|
216
251
|
name/id (no allowlist); a blank/whitespace value is rejected. Threaded to the
|
|
217
|
-
SDK's `Sandbox.create(template, opts)` on
|
|
218
|
-
single-participant and fan-out cua participants, and the shared-world subject
|
|
252
|
+
SDK's `Sandbox.create(template, opts)` on every desktop-creating route (the
|
|
253
|
+
single-participant and fan-out cua participants, and the shared-world subject and every actor
|
|
219
254
|
sandbox); when absent the call
|
|
220
255
|
stays the byte-stable `Sandbox.create(opts)` default (the stock template). The
|
|
221
256
|
template actually used is recorded in the run bundle as `desktopTemplate`
|
|
222
257
|
(public-safe, since a template name is not a secret). Inert (warned) on every route
|
|
223
258
|
that creates no desktop, incl. the in-process `local-app` cua route, so it is
|
|
224
|
-
never silently ignored
|
|
259
|
+
never silently ignored. Custom images need the
|
|
225
260
|
Desktop SDK's `xdotool` input support, `mktemp`, and the `C.UTF-8` locale:
|
|
226
261
|
every typed text is written to a private 0600 file and typed with
|
|
227
262
|
`LC_ALL=C.UTF-8 xdotool type --file` in one attempt. Without that locale a
|
|
@@ -238,79 +273,76 @@ dwell? }`. The parser expands it into
|
|
|
238
273
|
when known. Inert (warned) where this route-specific browser launcher is not
|
|
239
274
|
used;
|
|
240
275
|
- `execution.terminal` + `execution.runtimeAuth` (terminal-product route):
|
|
241
|
-
`terminal.transport` is `exec-stream`: captured
|
|
276
|
+
`terminal.transport` is `exec-stream`: captured non-interactive exec output
|
|
242
277
|
(stdin disabled); `pty` is rejected because labeling captured exec output as
|
|
243
|
-
an interactive PTY would overstate the mechanism (
|
|
244
|
-
|
|
278
|
+
an interactive PTY would overstate the mechanism (a duplex PTY
|
|
279
|
+
transport does not ship). `terminal.stdin` defaults to `disabled`
|
|
245
280
|
(`sent`/assisted input is rejected until the interventions ledger + a
|
|
246
281
|
non-comparable marker exist). `runtimeAuth` (`openai-env`, the default, or `openai-egress`)
|
|
247
|
-
declares the agent's runtime-auth channel, recorded as
|
|
282
|
+
declares the agent's runtime-auth channel, recorded as names only. On a live run, the engine
|
|
248
283
|
resolves the registered terminal descriptor and requires
|
|
249
284
|
`keyPlacement: in-sandbox-command-scoped` before creating a sandbox. With `openai-env`
|
|
250
285
|
the key is passed only to the agent command, never to `Sandbox.create` or
|
|
251
286
|
metadata; with `openai-egress` it stays in the host-side E2B header transform
|
|
252
287
|
set at sandbox creation, and the agent gets a placeholder. A dry-run neither
|
|
253
288
|
reads nor injects it;
|
|
254
|
-
- `
|
|
255
|
-
`
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
- `
|
|
289
|
+
- `mode`: `dry-run` (a synthetic bundle, no spend; the default) or `live`. On the
|
|
290
|
+
scripted route `live` gates real browser actuation against the declared app.
|
|
291
|
+
Provider spend stays $0 there by mechanism (no model runs);
|
|
292
|
+
- `scenario` (scripted route, required): a committed scenario id or path
|
|
293
|
+
(`humanish/scenarios/<id>.yaml` or a repo path) whose `browser.steps` are what
|
|
294
|
+
the actor executes, digest-pinned into bundle provenance. Every other route
|
|
295
|
+
refuses it;
|
|
296
|
+
- `caps` on the terminal route: `{ maxUsd, maxJobs, maxMinutes }`,
|
|
262
297
|
all non-negative numbers (0 = no-spend, the default). This budget bounds the
|
|
263
298
|
in-sandbox live key by mechanism: the live key is never exercised without a
|
|
264
299
|
fail-closed cap in force. `maxMinutes` is the
|
|
265
300
|
wall-clock kill; `maxUsd`/`maxJobs` are enforced fail-closed against the cost
|
|
266
|
-
ledger after the session (a run whose
|
|
267
|
-
`
|
|
301
|
+
ledger after the session (a run whose known spend exceeds the cap fails closed,
|
|
302
|
+
`HUMANISH_TERMINAL_CAPS_EXCEEDED`). Core records Codex provider spend as
|
|
268
303
|
unpriced tokens, so without a cost probe no line can trip a positive `maxUsd`:
|
|
269
304
|
a live run refuses `maxUsd > 0` before creating a sandbox
|
|
270
|
-
(`
|
|
305
|
+
(`HUMANISH_TERMINAL_UNPRICED_CAP`) unless the caller passes a `costProbe`
|
|
271
306
|
hook. The sandbox's server-side timeout is the steps before the
|
|
272
307
|
codex command (Node bootstrap, runtime version check, and product setup when
|
|
273
308
|
`subject.product.install` is declared) plus `maxMinutes` plus a 5-minute
|
|
274
309
|
teardown buffer; a live run refuses a `maxMinutes` that would take it past
|
|
275
|
-
E2B's one-hour limit (`
|
|
276
|
-
Terminal Cost Ledger And No-Spend Proof).
|
|
277
|
-
|
|
278
|
-
`scenario.caps.maxUsd` or `scenario.caps.maxTotalUsd` on a computer-use lab
|
|
279
|
-
is a parse error naming the matching `execution.caps` field, which is what
|
|
280
|
-
that route enforces;
|
|
310
|
+
E2B's one-hour limit (`HUMANISH_TERMINAL_CAPS_INVALID`). The no-spend proof is derived from that real ledger, never asserted (see
|
|
311
|
+
Terminal Cost Ledger And No-Spend Proof). `maxTotalUsd` is refused on the
|
|
312
|
+
terminal route;
|
|
281
313
|
- `policies`: `redactRepos`, `redactScreenshots`, `allowPublicTargets`,
|
|
282
314
|
`mediaPermission` (`prompt` | `granted`), and the
|
|
283
315
|
terminal-product credential-boundary booleans `allowPrivateRepoAccess`,
|
|
284
316
|
`allowProviderCredentials`, `allowPaymentCredentials`, `allowGitHubMutation`
|
|
285
|
-
(all
|
|
317
|
+
(all default false, deny-by-default; only the runtime LLM key enters, and
|
|
286
318
|
only command-scoped). The scripted-browser route is loopback-only and rejects
|
|
287
319
|
`redactScreenshots: true` (blur unimplemented there) and
|
|
288
320
|
`allowPublicTargets: true` fail-closed rather than ignoring them.
|
|
289
|
-
- `comms` (
|
|
321
|
+
- `comms` (hosted on the clone/local-tree computer-use route and the
|
|
290
322
|
shared-world getHost plane, or connected to an external catch on
|
|
291
323
|
app-url/operator-provided subjects): off-app
|
|
292
|
-
email the app itself sends, made a persona-driven testable surface.
|
|
324
|
+
email the app itself sends, made a persona-driven testable surface. Study
|
|
293
325
|
configuration rejects `comms.sms` and unknown channel names; message-bus SMS
|
|
294
326
|
types do not imply a supported SMS execution route. SMTP capture is supported
|
|
295
327
|
on provisioned routes with separate worlds and rejected for shared-world studies.
|
|
296
328
|
`comms.email` = `{ kind: fake, injectEnv?, port?, smtp?, recipients?, linkOrigin?, external? }`.
|
|
297
|
-
`injectEnv` is the
|
|
329
|
+
`injectEnv` is the adopter-named env var the app reads for its email-API base
|
|
298
330
|
URL (e.g. `RESEND_API_URL`); the harness sets it to an in-sandbox catch (so it
|
|
299
|
-
is
|
|
331
|
+
is not declared in `subject.env`) that captures the app's sends without touching
|
|
300
332
|
the internet. Verify the app actually reads that variable, because a run whose
|
|
301
333
|
catch captured zero sends warns at teardown for exactly that. `kind` must be
|
|
302
334
|
`fake`; a real inbox names a saved `comms.email.connection` instead; `port` ≤ 65534
|
|
303
335
|
(the catch reserves `port+1` for the read-only inbox listener the shared-world
|
|
304
|
-
route getHost-exposes). `recipients[]` = `{ lane, address? }`:
|
|
336
|
+
route getHost-exposes). `recipients[]` = `{ lane, address? }`: omit the list
|
|
305
337
|
and the parser fills one deterministic address per participant
|
|
306
|
-
(`<laneId>@example.test`) so every participant can do email
|
|
307
|
-
`lane` must be one of the
|
|
308
|
-
`lane-01..lane-NN` under
|
|
338
|
+
(`<laneId>@example.test`) so every participant can do email. When declared, a
|
|
339
|
+
`lane` must be one of the study's real participant ids (list or group ids, or the
|
|
340
|
+
generated `lane-01..lane-NN` under a count). An unknown participant id is a hard parse error
|
|
309
341
|
listing them, zero addressed participants is a hard error, partial coverage warns
|
|
310
342
|
with the uncovered participants. Each addressed participant's actor prompt is extended with
|
|
311
343
|
the full handoff: its address ("enter exactly that"), the inbox URL, and the
|
|
312
344
|
wait steering ("waiting for an email is normal, not a blocker").
|
|
313
|
-
`external`
|
|
345
|
+
`external` switches the funnel to an adopter-hosted catch, which is what
|
|
314
346
|
makes comms work on planes humanish does not provision (app-url /
|
|
315
347
|
operator-provisioned): `{ catchBaseUrl, inboxBaseUrl?, authTokenEnv? }`. The
|
|
316
348
|
operator runs the catch and points their own app's email-API base URL at it.
|
|
@@ -323,19 +355,19 @@ dwell? }`. The parser expands it into
|
|
|
323
355
|
`humanish-comms-catch` marker, so a proxy answering 200 for everything cannot
|
|
324
356
|
pass for a catch), the teardown drain over `GET /deliveries`, and the same
|
|
325
357
|
digest-only evidence. `authTokenEnv` names an env var holding a bearer token
|
|
326
|
-
for the drain read. The
|
|
358
|
+
for the drain read. The name is recorded as evidence; the value never
|
|
327
359
|
persists. A live run refuses a token shorter than 16 characters, or not
|
|
328
360
|
well-formed Unicode, before it probes the catch
|
|
329
|
-
(`
|
|
330
|
-
`
|
|
361
|
+
(`HUMANISH_COMPUTER_USE_COMMS_TOKEN_INVALID`,
|
|
362
|
+
`HUMANISH_SHARED_WORLD_COMMS_TOKEN_INVALID`), as
|
|
331
363
|
`humanish comms catch --token` does, and scrubs the token and its encoded
|
|
332
364
|
forms from every comms warning. Declaring `external` on a harness-provisioned subject warns: two
|
|
333
365
|
catches would exist and the app would point at humanish's own. `linkOrigin`
|
|
334
366
|
is an optional operator-declared origin the app bakes into links when it
|
|
335
367
|
differs from the serve origin; the harness rewrites captured links through it
|
|
336
368
|
so a clicked link resolves to a reachable host. Captured mail is drained into a
|
|
337
|
-
digest-only `humanish.comms-thread.v1` artifact (from/to/subject/link
|
|
338
|
-
an OTP
|
|
369
|
+
digest-only `humanish.comms-thread.v1` artifact (from/to/subject/link digests +
|
|
370
|
+
an OTP count; no raw address/link/code persists). The readable proof a
|
|
339
371
|
persona saw the email is its screenshots of the inbox page. Requires `python3`
|
|
340
372
|
in the subject sandbox (the stock E2B desktop template has it).
|
|
341
373
|
|
|
@@ -361,7 +393,7 @@ Adding an existing name with different settings refuses to overwrite it.
|
|
|
361
393
|
profiles and local key presence/source, not provider authentication or delivery.
|
|
362
394
|
`comms providers --json` returns `humanish.comms-providers.v1` with explicit
|
|
363
395
|
setup/receiving availability. The key store accepts `humanish keys set agentmail`.
|
|
364
|
-
Saving a connection neither modifies a
|
|
396
|
+
Saving a connection neither modifies a study nor creates a provider resource;
|
|
365
397
|
a supported study explicitly selects `comms.email: { connection: agentmail }`.
|
|
366
398
|
Optional `allowedOrigins` lists exact additional HTTP(S) origins; `linkOrigin`
|
|
367
399
|
participates in the existing provisioned-subject origin rewrite. Connection
|
|
@@ -379,15 +411,15 @@ acquisition and cleanup status. It contains no raw addresses, bodies, provider I
|
|
|
379
411
|
or content digests. `run.json` embeds the final projection as `commsReceiving` and
|
|
380
412
|
carries `publication.restrictions: [real-communications]`. Verification keeps the
|
|
381
413
|
run local-only regardless of screenshot redaction. See the
|
|
382
|
-
[receiving contract](
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
`
|
|
386
|
-
|
|
387
|
-
`
|
|
388
|
-
`humanish.run-bundle.v1` in every case.
|
|
389
|
-
|
|
390
|
-
per-participant session budget, worst-case sandbox-minutes), `lanes[]` (
|
|
414
|
+
[receiving contract](https://humanish.dev/docs/email-receiving).
|
|
415
|
+
|
|
416
|
+
A study's result has one schema on every route, `humanish.study-result.v1`
|
|
417
|
+
(`src/run/study-result.ts`), with `route` and `studyId`. 0.109.0 removed `labId`, which 0.108.0
|
|
418
|
+
wrote with the same value. Route-specific fields stay on their route's result. `humanish run`
|
|
419
|
+
with no study, `observe`, and a refusal made before a route is picked keep
|
|
420
|
+
`humanish.run-result.v1`. The evidence record stays `humanish.run-bundle.v1` in every case.
|
|
421
|
+
The computer-use result carries `plan` (the pre-flight participant table: concurrency, waves,
|
|
422
|
+
per-participant session budget, worst-case sandbox-minutes), `lanes[]` (always present,
|
|
391
423
|
length 1 at N=1; per-participant status/session/sandbox/subject), and `laneSummary`
|
|
392
424
|
(passed/skipped/harnessErrors/hollow counts). The top-level `session`/`sandbox`
|
|
393
425
|
mirror the first participant and `subject.commit` is unanimity-gated across participants
|
|
@@ -396,14 +428,14 @@ the run bundle is byte-stable with the pre-fan-out output; only the result
|
|
|
396
428
|
projection changed. A fan-out run records a `cua-lab.fanout.plan` bundle event
|
|
397
429
|
(and a `cua-lab.fanout.fail-fast` event when a harness error skips queued participants);
|
|
398
430
|
`ok = observer.ok ∧ every participant ok ∧ no failed adapter or declared-scorer verdict`,
|
|
399
|
-
where a dry-run participant is ok as
|
|
431
|
+
where a dry-run participant is ok as synthetic and a live participant must pass
|
|
400
432
|
`participantPassed` (`src/run/judge.ts`): not skipped, status `passed`, no harness
|
|
401
433
|
error, engaged, and no self-reported blocker.
|
|
402
434
|
|
|
403
435
|
Explicit failed-participant reruns are supported on the CUA fan-out route via
|
|
404
|
-
`humanish
|
|
405
|
-
participant id is a declared `
|
|
406
|
-
The source run must be a live CUA fan-out bundle. humanish creates a
|
|
436
|
+
`humanish run <study> --rerun-failed-from <run-id> [--participants <ids>]`, where a
|
|
437
|
+
participant id is a declared `participants` entry id, or `lane-01`, `lane-02`, … by position.
|
|
438
|
+
The source run must be a live CUA fan-out bundle. humanish creates a new run for
|
|
407
439
|
the selected failed/blocked/timed-out/hollow participants (or explicit participant ids), leaves
|
|
408
440
|
the source verdict unchanged, and records lineage as `run.rerun` plus a
|
|
409
441
|
`cua-lab.fanout.rerun` event: source run id, selected participant ids, and previous participant
|
|
@@ -414,26 +446,32 @@ That field is the judge's status (`judgedStatus` in `src/run/judge.ts`), so a go
|
|
|
414
446
|
session that reported a blocker counts as blocked. A source bundle without `judgedStatus` falls back
|
|
415
447
|
to the stream's trace status, its actor status and completion reason, and a zero-action check.
|
|
416
448
|
|
|
417
|
-
|
|
418
|
-
committed public-safe
|
|
419
|
-
`.humanish/local/
|
|
420
|
-
not
|
|
421
|
-
|
|
449
|
+
Study files are human-authored `.yaml` source under `humanish/studies/*.yaml` for
|
|
450
|
+
committed public-safe studies, or ignored `.humanish/studies/*.yaml` /
|
|
451
|
+
`.humanish/local/studies/*.yaml` for private local dogfood. A v3 key the declared route
|
|
452
|
+
does not read is an error, so a study file never silently claims behavior that did not run.
|
|
453
|
+
A name found only in one of the three `labs/` directories is refused: a v2 file with
|
|
454
|
+
`HUMANISH_STUDY_V2_UNSUPPORTED`, and a v3 file with `HUMANISH_STUDY_RETIRED_DIRECTORY`, whose
|
|
455
|
+
message names the matching `studies/` directory to move it to. A path to a v3 file runs wherever
|
|
456
|
+
the file is. `study list --json`
|
|
457
|
+
lists the refused files in `retired`, each `{ path, code, message }`.
|
|
422
458
|
|
|
423
|
-
Committed fixture (`humanish/
|
|
459
|
+
Committed fixture (`humanish/studies/first-run.yaml`):
|
|
424
460
|
|
|
425
461
|
```yaml
|
|
426
|
-
schema: humanish.
|
|
462
|
+
schema: humanish.study.v3
|
|
427
463
|
id: first-run
|
|
428
464
|
title: First-run synthetic Observer
|
|
429
|
-
description:
|
|
465
|
+
description: >-
|
|
466
|
+
Writes a preview run: a synthetic run bundle and Observer for four participants. Needs no browser,
|
|
467
|
+
model or keys, and costs nothing. Run it with humanish run first-run.
|
|
468
|
+
route: preview
|
|
469
|
+
mode: dry-run
|
|
430
470
|
subject:
|
|
431
471
|
source: this-repo
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
scenario:
|
|
436
|
-
mode: dry-run
|
|
472
|
+
actor:
|
|
473
|
+
type: synthetic-persona
|
|
474
|
+
participants: 4
|
|
437
475
|
defaults:
|
|
438
476
|
open: true
|
|
439
477
|
```
|
|
@@ -462,38 +500,39 @@ Core-owned fields:
|
|
|
462
500
|
- `artifacts`
|
|
463
501
|
- `review`
|
|
464
502
|
- `feedbackCandidates`
|
|
465
|
-
- `
|
|
466
|
-
`{ id, path?, origin? }`, where `origin` is `committed` (humanish/
|
|
467
|
-
`ignored` (a local overlay), or `explicit` (a path
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
`
|
|
472
|
-
|
|
503
|
+
- `study` (optional, additive): which study file produced the run,
|
|
504
|
+
`{ id, path?, origin? }`, where `origin` is `committed` (`humanish/studies/`; a run saved by
|
|
505
|
+
0.108 or earlier can name `humanish/labs/`), `ignored` (a local overlay), or `explicit` (a path
|
|
506
|
+
the operator passed). Runs saved by 0.108 and earlier also have `lab` with the same value;
|
|
507
|
+
0.109 writes `study` only. `study` is absent on bundles written before this contract and on
|
|
508
|
+
library callers who hand a `StudyConfig` directly; such a run has no study. Readers go through
|
|
509
|
+
`studyProvenanceOf` (`src/run/study-provenance.ts`): a valid `study`, else a valid `lab` from
|
|
510
|
+
an older run, else `inferLegacyStudyId`, which reads the `persona.source` or `scenario.source`
|
|
511
|
+
convention `study:<id>`, or `lab:<id>` from runs written before 0.108, and nothing else.
|
|
473
512
|
- `subject` (optional, additive): structured subject provenance,
|
|
474
513
|
`{ source: clone | app-url | local-tree, repo?, commit?, archiveSha256?,
|
|
475
514
|
dirty?, envNames?, state }` where `state` is `{ provenance: seeded |
|
|
476
515
|
unpinned | declared-not-run | undeclared | external-public, seed?: [{ name, when,
|
|
477
516
|
commandDigest, ok?, exitCode?, timedOut?, durationMs? }], externalEnvNames?
|
|
478
|
-
}`. Emitted by the computer-use and shared-world
|
|
517
|
+
}`. Emitted by the computer-use and shared-world routes and the clone
|
|
479
518
|
scripted-browser route; absent on pre-existing and other bundles. `repo`/`commit` are clone-route fields; `archiveSha256`
|
|
480
519
|
(64-hex sha256, the local-tree provenance pin) and `dirty` (host git
|
|
481
520
|
porcelain status at pack time) are local-tree-route fields, additive under
|
|
482
521
|
`humanish.run-bundle.v1`: a dirty working tree cannot be commit-pinned, so
|
|
483
522
|
the archive content digest stands in for it. `commandDigest` is the
|
|
484
523
|
sha256-16 of the exact seed command; command text and env values never
|
|
485
|
-
appear. `humanish verify` fails closed when a
|
|
524
|
+
appear. `humanish verify` fails closed when a live `local-tree` bundle carries
|
|
486
525
|
no well-formed `archiveSha256`, in addition to the existing `subject state
|
|
487
526
|
provenance` check.
|
|
488
|
-
- `desktopTemplate` (optional, additive): the custom E2B desktop
|
|
527
|
+
- `desktopTemplate` (optional, additive): the custom E2B desktop template (image)
|
|
489
528
|
the run's sandbox(es) launched on, from `execution.desktop.template`, so the
|
|
490
|
-
evidence shows
|
|
529
|
+
evidence shows which image ran. Present only when a template was configured;
|
|
491
530
|
absent == the stock `desktop` template, so every pre-existing bundle is
|
|
492
531
|
byte-stable. Public-safe (a template name is not a secret).
|
|
493
532
|
- `attributionClass` (optional, additive): `isolated | shared-world`. Absent ==
|
|
494
533
|
`isolated`, so every existing bundle is byte-stable. It is the
|
|
495
|
-
interaction-attribution axis
|
|
496
|
-
evidence classes. Set to `shared-world` by the shared-world
|
|
534
|
+
interaction-attribution axis, independent of the persona-sampling
|
|
535
|
+
evidence classes. Set to `shared-world` by the shared-world route, paired
|
|
497
536
|
with `sharedWorld`.
|
|
498
537
|
- `sharedWorld` (optional, additive): the shared-world evidence block
|
|
499
538
|
(`humanish.shared-world.v1`); see [Shared-World Evidence](#shared-world-evidence)
|
|
@@ -567,43 +606,43 @@ feedbackCandidates: []
|
|
|
567
606
|
|
|
568
607
|
## Shared-World Evidence
|
|
569
608
|
|
|
570
|
-
The shared-world topology
|
|
571
|
-
default: N distinct participants drive
|
|
572
|
-
app + one seeded DB) so their actions interact through shared state. The
|
|
609
|
+
The shared-world topology is the declared override of the `per-lane-worlds`
|
|
610
|
+
default: N distinct participants drive one provisioned, mutable service plane (one
|
|
611
|
+
app + one seeded DB) so their actions interact through shared state. The one
|
|
573
612
|
subject plane is provisioned via `subject.source: clone` (a fresh `git clone`) or
|
|
574
613
|
`subject.source: local-tree` (the operator's own working tree, packed on the host
|
|
575
614
|
and provisioned in-sandbox in place of a clone - see `subject.localTree` above);
|
|
576
615
|
both sources are accepted on the shared-world route.
|
|
577
616
|
|
|
578
|
-
Current runs write only the
|
|
617
|
+
Current runs write only the concurrent shape below. The sequential shape came from the
|
|
579
618
|
sequential shared-world route, which 0.106.0 removed. Only bundles written before
|
|
580
619
|
0.106.0 carry it, and `humanish verify` still checks them
|
|
581
|
-
(`tests/run/legacy-sequential-shared-world.test.ts`). The
|
|
620
|
+
(`tests/run/legacy-sequential-shared-world.test.ts`). The sequential rules below apply
|
|
582
621
|
to those bundles.
|
|
583
622
|
|
|
584
|
-
A shared-world bundle adds
|
|
623
|
+
A shared-world bundle adds two additive, optional fields to `humanish.run-bundle.v1`
|
|
585
624
|
(absent on every other bundle, so they stay byte-stable):
|
|
586
625
|
|
|
587
626
|
- `attributionClass: isolated | shared-world`: a separate attribution axis
|
|
588
|
-
("how well did the run attribute
|
|
627
|
+
("how well did the run attribute interaction?"), distinct from the persona-sampling
|
|
589
628
|
evidence classes ("how representative is the actor?"). Absent == `isolated`.
|
|
590
|
-
- `sharedWorld` (`humanish.shared-world.v1`):
|
|
629
|
+
- `sharedWorld` (`humanish.shared-world.v1`): two variants discriminated by
|
|
591
630
|
`topologyMode: "sequential" | "concurrent"` (`sharedWorldEvidenceFindings` in `src/verify/shared-world.ts` branches on
|
|
592
|
-
it
|
|
631
|
+
it first; unknown/missing or a mismatched shape fails closed). Common fields:
|
|
593
632
|
- `topology: shared-world`
|
|
594
633
|
- `topologyMode: sequential | concurrent`
|
|
595
|
-
- `roleCount`: the
|
|
596
|
-
- `plane: { commit?, seedDigest, envNames, hostDigest?, exposure?, publicOriginDigest?, declaredOriginDigest? }`: the
|
|
634
|
+
- `roleCount`: the declared number of participants.
|
|
635
|
+
- `plane: { commit?, seedDigest, envNames, hostDigest?, exposure?, publicOriginDigest?, declaredOriginDigest? }`: the one
|
|
597
636
|
shared-plane provenance. `seedDigest` is the sha256-16 of the ordered seed-step
|
|
598
|
-
command digests (the seed
|
|
599
|
-
|
|
600
|
-
`publicOriginDigest` is
|
|
637
|
+
command digests (the seed recipe identity, not the runtime state); `envNames` are
|
|
638
|
+
names only. `hostDigest`/`exposure` are concurrent provisioned-getHost-only, and
|
|
639
|
+
`publicOriginDigest` is concurrent external-public-only (below).
|
|
601
640
|
- `planeClass?: provisioned-getHost | external-public` and `lobbyConvergenceDigest?` are
|
|
602
|
-
|
|
641
|
+
concurrent-only (below); both absent on the sequential shape.
|
|
603
642
|
- `attributionLimits: [...]`: the verify-enforced attribution ceiling (the set
|
|
604
643
|
differs per `topologyMode`, below).
|
|
605
644
|
|
|
606
|
-
|
|
645
|
+
Sequential shape (`topologyMode: sequential`; only in bundles written before
|
|
607
646
|
0.106.0):
|
|
608
647
|
- `sequence: [roleId, …]`: the role ids that actually took a turn, in declared order.
|
|
609
648
|
- `skippedTail` (optional, live sequential only): `{ afterRoleId, roles,
|
|
@@ -620,121 +659,121 @@ cause, maxTotalUsd?, estimatedTotalUsd? }`. Each ordered `roles` entry names
|
|
|
620
659
|
timeline that starts `cp-baseline`, alternates checkpoint → turn → checkpoint,
|
|
621
660
|
and ends on a checkpoint:
|
|
622
661
|
- checkpoint = `{ kind: checkpoint, name, digest, deltaFromPrev }`; `digest` is
|
|
623
|
-
sha256-16(scrub+redact(probe stdout)); the record is
|
|
662
|
+
sha256-16(scrub+redact(probe stdout)); the record is digest-only (no
|
|
624
663
|
value-shaped field). `deltaFromPrev` is true when the observed state changed
|
|
625
664
|
across the intervening turn.
|
|
626
665
|
- turn = `{ kind: turn, roleId, simId, streamId, commit?, seedDigest }` references
|
|
627
666
|
a real `RunBundle["simulations"][number]` and `RunBundle["streams"][number]`; carries the
|
|
628
667
|
plane provenance it observed
|
|
629
668
|
(identical across turns by construction; this is the single-plane proof).
|
|
630
|
-
- Sequential `attributionLimits`
|
|
669
|
+
- Sequential `attributionLimits` must contain `sequential-only`, `no-concurrent-races`,
|
|
631
670
|
and `delta-attributed-to-turn-not-action`.
|
|
632
671
|
|
|
633
|
-
|
|
634
|
-
getHost-exposed plane
|
|
635
|
-
- `plane.hostDigest`: sha256-16 of the harness-minted `getHost`
|
|
636
|
-
drove (a first-class provisioned-subject target
|
|
672
|
+
Concurrent shape (`topologyMode: concurrent`: N personas drive one
|
|
673
|
+
getHost-exposed plane at once; no `timeline`/`sequence`):
|
|
674
|
+
- `plane.hostDigest`: sha256-16 of the harness-minted `getHost` origin every actor
|
|
675
|
+
drove (a first-class provisioned-subject target). A digest, not the raw
|
|
637
676
|
URL: a getHost URL embeds the live sandbox id and matches the publish-safety e2b-URL
|
|
638
677
|
redaction, so it never lands raw in a published bundle (the raw tokenless URL is
|
|
639
|
-
surfaced only on the ephemeral
|
|
640
|
-
|
|
641
|
-
- `plane.exposure: synthetic`: the
|
|
678
|
+
surfaced only on the ephemeral study result). The orchestrator confirms the URL is
|
|
679
|
+
tokenless (no authKey) before digesting.
|
|
680
|
+
- `plane.exposure: synthetic`: the required author attestation that the subject behind
|
|
642
681
|
the internet-reachable getHost URL is synthetic seeded data (author-trust + a
|
|
643
|
-
provenance gate,
|
|
682
|
+
provenance gate, not a no-real-data guarantee).
|
|
644
683
|
- `laneWindows: [{ roleId, simId, streamId, startedAt, endedAt, verdict, routeHostDigest,
|
|
645
|
-
commit?, seedDigest }]`: one harness-clocked window per actor;
|
|
684
|
+
commit?, seedDigest }]`: one harness-clocked window per actor; overlapping windows
|
|
646
685
|
prove ≥2 personas were active simultaneously. `routeHostDigest` == `plane.hostDigest`
|
|
647
686
|
(every actor drove exactly the harness-minted host).
|
|
648
687
|
- `stateSeries: [{ timestamp, digest }]`: cadence digests of the shared world under
|
|
649
|
-
load (baseline + periodic + final).
|
|
650
|
-
|
|
688
|
+
load (baseline + periodic + final). Digest-only: the allowed-keys tripwire permits
|
|
689
|
+
only `timestamp` + `digest` (no per-delta→actor field, because causation under concurrency
|
|
651
690
|
is structurally inexpressible).
|
|
652
691
|
- `outcomes: [{ roleId, simId, streamId, status, completionReason?, ok }]`: per-persona
|
|
653
|
-
|
|
654
|
-
- Concurrent `attributionLimits`
|
|
692
|
+
outcome (the "M of N succeeded" headline).
|
|
693
|
+
- Concurrent `attributionLimits` must contain `concurrent`,
|
|
655
694
|
`best-effort-causal-attribution`, `non-deterministic-shared-state`,
|
|
656
695
|
`window-and-snapshot-granularity`, `contention-observed-not-proven-safe`,
|
|
657
|
-
`state-change-not-isolated-to-actors`, and
|
|
696
|
+
`state-change-not-isolated-to-actors`, and must not contain `sequential-only` or
|
|
658
697
|
`no-concurrent-races` (a sequential guarantee on a concurrent run is an overclaim).
|
|
659
698
|
|
|
660
699
|
The `shared-world evidence` check in `humanish verify` is fail-closed (live runs only;
|
|
661
|
-
dry-run contract bundles are skipped). It dispatches on `topologyMode`
|
|
662
|
-
|
|
700
|
+
dry-run contract bundles are skipped). It dispatches on `topologyMode` first.
|
|
701
|
+
Sequential: the timeline must be well-formed (start `cp-baseline`, strictly alternate,
|
|
663
702
|
end on a checkpoint, turn order == sequence, sequence length == roleCount == turn
|
|
664
703
|
count, no `laneWindows`); every turn's simId/streamId resolves; every checkpoint digest
|
|
665
|
-
is sha256-16 with
|
|
666
|
-
mandatory limits are present; and a
|
|
667
|
-
delta-on-pass gate).
|
|
668
|
-
cover exactly roleCount and stateSeries is present; the required limits are present
|
|
669
|
-
`plane.hostDigest` present and every `routeHostDigest` equals it
|
|
670
|
-
`plane.exposure == synthetic`
|
|
704
|
+
is sha256-16 with no value-shaped field; all turns share one plane provenance; the
|
|
705
|
+
mandatory limits are present; and a passed run shows ≥1 checkpoint `deltaFromPrev` (the
|
|
706
|
+
delta-on-pass gate). Concurrent: no `timeline`; laneWindows and outcomes each
|
|
707
|
+
cover exactly roleCount and stateSeries is present; the required limits are present and the forbidden ones absent;
|
|
708
|
+
`plane.hostDigest` present and every `routeHostDigest` equals it;
|
|
709
|
+
`plane.exposure == synthetic` and `subject.state.provenance == seeded` (the
|
|
671
710
|
synthetic-subject gate); stateSeries snapshots are digest-only (allowed-keys tripwire);
|
|
672
|
-
all laneWindows share
|
|
673
|
-
run
|
|
711
|
+
all laneWindows share one plane provenance; and the concurrency-on-pass gate: a passed
|
|
712
|
+
run must show ≥2 overlapping laneWindows and a stateSeries delta whose timestamp is
|
|
674
713
|
AT/AFTER an overlap interval start (otherwise it was not actually concurrent, or the
|
|
675
714
|
world never changed under load). The per-participant no-engagement guard applies to both.
|
|
676
|
-
Checkpoints / stateSeries persist digest-only by
|
|
677
|
-
detector lands.
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
fidelity; the
|
|
681
|
-
|
|
682
|
-
the checkpoint after A strictly precedes B's turn). It
|
|
683
|
-
causation, concurrency/races (sequential-only), or exact-state determinism.
|
|
684
|
-
each persona's own behavior at full fidelity; per-persona
|
|
685
|
-
world ("M of N");
|
|
686
|
-
under load (the stateSeries) with best-effort temporal correlation. It
|
|
715
|
+
Checkpoints / stateSeries persist digest-only by default until the
|
|
716
|
+
[PII/PHI detector](https://github.com/danielgwilson/humanish/issues/108) lands.
|
|
717
|
+
|
|
718
|
+
What the bundle can / cannot claim. Sequential: each role's own behavior at full
|
|
719
|
+
fidelity; the observed system outcome as an ordered digest sequence; and the
|
|
720
|
+
sequenced-interaction proof (role B entered a world already containing role A's mutation;
|
|
721
|
+
the checkpoint after A strictly precedes B's turn). It cannot claim action-granular
|
|
722
|
+
causation, concurrency/races (sequential-only), or exact-state determinism. Concurrent:
|
|
723
|
+
each persona's own behavior at full fidelity; per-persona outcome against the contended
|
|
724
|
+
world ("M of N"); proven concurrency (overlapping windows); and system-state evolution
|
|
725
|
+
under load (the stateSeries) with best-effort temporal correlation. It cannot claim
|
|
687
726
|
strict causal attribution of a delta to an actor (concurrent ⇒ ambiguous), determinism
|
|
688
|
-
of exact state, per-action granularity, or concurrency-
|
|
689
|
-
|
|
727
|
+
of exact state, per-action granularity, or concurrency-safety (races are observed, never
|
|
728
|
+
proven absent). Limits: the deterministic $0 gate proves the plumbing + the
|
|
690
729
|
attribution contract. A kept 2026-06-17 live receipt separately proves one
|
|
691
730
|
bounded three-persona trial against a synthetic plane. Neither the deterministic
|
|
692
731
|
gate nor that receipt proves scale, repeatability, or adopter-harness replacement.
|
|
693
732
|
|
|
694
|
-
### Concurrent plane classes: provisioned
|
|
733
|
+
### Concurrent plane classes: provisioned and external-public
|
|
695
734
|
|
|
696
|
-
The
|
|
735
|
+
The concurrent shape carries a plane-class discriminator, `sharedWorld.planeClass:
|
|
697
736
|
"provisioned-getHost" | "external-public"`. Absent == `provisioned-getHost` (every existing
|
|
698
|
-
concurrent bundle byte-stable). It gates
|
|
737
|
+
concurrent bundle byte-stable). It gates every getHost-specific verify assertion, so a getHost
|
|
699
738
|
claim can never leak onto the external-public class (or vice versa).
|
|
700
739
|
|
|
701
740
|
- `provisioned-getHost`: the historical plane described above: a `clone`/`local-tree` subject the
|
|
702
|
-
harness serves + getHost-exposes in-sandbox. The harness
|
|
741
|
+
harness serves + getHost-exposes in-sandbox. The harness minted the host, so it asserts the
|
|
703
742
|
synthetic-seeded attestation (`plane.exposure: synthetic` + `subject.state.provenance == seeded`),
|
|
704
743
|
the harness-minted host identity (`plane.hostDigest`, every `routeHostDigest == it`), and an
|
|
705
744
|
authoritative in-sandbox checkpoint `stateSeries` with a delta-on-pass.
|
|
706
745
|
|
|
707
|
-
- `external-public`: a real, operator-
|
|
708
|
-
(`subject.source: app-url` + `
|
|
709
|
-
`execution.concurrency > 1`).
|
|
746
|
+
- `external-public`: a real, operator-owned public deployment used directly as the shared plane
|
|
747
|
+
(`subject.source: app-url` + `route: shared-world` + `policies.allowPublicTargets: true` +
|
|
748
|
+
`execution.concurrency > 1`). No getHost, no clone, no subject sandbox, no seed. The subject
|
|
710
749
|
carries the ownership attestation `subject.publicTarget: { owner, authorized: true }` (the
|
|
711
|
-
analog of `exposure: synthetic`: you cannot attest synthetic on a real site, but you
|
|
750
|
+
analog of `exposure: synthetic`: you cannot attest synthetic on a real site, but you must attest
|
|
712
751
|
you own/operate it; author-trust, unverifiable by the harness). Evidence deltas, all
|
|
713
752
|
asserted-absent (never silently dropped):
|
|
714
|
-
- `plane.publicOriginDigest`: sha256-16 of the one
|
|
715
|
-
`laneWindow.routeHostDigest` (computed from that participant's CDP-
|
|
753
|
+
- `plane.publicOriginDigest`: sha256-16 of the one observed origin the participants converged on. Every
|
|
754
|
+
`laneWindow.routeHostDigest` (computed from that participant's CDP-observed final-URL origin) equals it.
|
|
716
755
|
`plane.declaredOriginDigest` records the operator-declared origin as evidence only; a redirect
|
|
717
|
-
can make the two differ. This proves inter-participant
|
|
718
|
-
(
|
|
719
|
-
- `plane.exposure` is
|
|
756
|
+
can make the two differ. This proves inter-participant convergence on one origin, not harness control of the plane
|
|
757
|
+
(weaker than getHost's `hostDigest`, and disclosed).
|
|
758
|
+
- `plane.exposure` is absent (verify fails closed if `synthetic` appears, since that
|
|
720
759
|
attestation would be false on a real site);
|
|
721
|
-
`plane.hostDigest` is
|
|
760
|
+
`plane.hostDigest` is absent (the harness minted no host).
|
|
722
761
|
- `subject.state.provenance == "external-public"` (never `seeded`, `unpinned` or `undeclared`).
|
|
723
|
-
- `stateSeries` is
|
|
724
|
-
is
|
|
725
|
-
|
|
726
|
-
- `lobbyConvergenceDigest` (optional, strong, cheap): sha256-16 of the shared `/lobby/CODE`
|
|
727
|
-
all participants' CDP URLs converged on; present only when every participant converged on
|
|
762
|
+
- `stateSeries` is omitted (Option A): no in-sandbox filesystem to authoritatively digest, so there
|
|
763
|
+
is no authoritative shared-state proof. Concurrency-on-pass is relaxed to temporal co-occupancy
|
|
764
|
+
only (≥2 overlapping `laneWindows`); there is no state-delta requirement.
|
|
765
|
+
- `lobbyConvergenceDigest` (optional, strong, cheap): sha256-16 of the shared `/lobby/CODE` path
|
|
766
|
+
all participants' CDP URLs converged on; present only when every participant converged on one code. Digest-only
|
|
728
767
|
(the raw 6-char code and full URLs are runtime-only and never land).
|
|
729
|
-
- `attributionLimits`
|
|
768
|
+
- `attributionLimits` must contain the concurrent family plus `external-public-plane`,
|
|
730
769
|
`operator-attested-target-not-harness-controlled`, `no-synthetic-attestation`,
|
|
731
|
-
`no-authoritative-shared-state-proof`, `concurrency-by-temporal-co-occupancy-only`; and
|
|
770
|
+
`no-authoritative-shared-state-proof`, `concurrency-by-temporal-co-occupancy-only`; and must not
|
|
732
771
|
contain `sequential-only`, `no-concurrent-races`, or any `seeded`/`synthetic` limit.
|
|
733
772
|
|
|
734
|
-
The getHost synthetic gate is deliberately
|
|
735
|
-
exists because getHost is internet-reachable
|
|
773
|
+
The getHost synthetic gate is deliberately not reachable from the app-url branch, and why: that gate
|
|
774
|
+
exists because getHost is internet-reachable and harness-owned (real data behind a harness-exposed
|
|
736
775
|
URL is the hazard). A public site the harness neither provisioned nor exposed has neither property,
|
|
737
|
-
so the gate's hazard does not exist there. Attribution stays `shared-world` (N participants,
|
|
776
|
+
so the gate's hazard does not exist there. Attribution stays `shared-world` (N participants, one plane); the
|
|
738
777
|
plane-control claim degrades from "harness-controlled" to "operator-attested, observed-only".
|
|
739
778
|
|
|
740
779
|
## Adapter
|
|
@@ -829,7 +868,7 @@ Legacy profiles retain medium defaults. `none_declared`/`none` access needs are
|
|
|
829
868
|
omitted. `keyboard_first` allows pointer fallback; `keyboard_only` does not.
|
|
830
869
|
These are prompt instructions, not evidence that a participant complied.
|
|
831
870
|
|
|
832
|
-
`humanish
|
|
871
|
+
`humanish study show` adds `personas: [{ id, resolved, brief? }]`. A brief contains
|
|
833
872
|
`compilerVersion`, persona-section `text`, its pre-redaction `digest`, `redacted`,
|
|
834
873
|
and an optional source-file `sourceDigest`. It excludes task criteria and runtime
|
|
835
874
|
grants. This is authored context; whether a selected actor consumes it depends on
|
|
@@ -858,7 +897,7 @@ Actors execute or simulate the trial. Actor evidence is the provider-neutral
|
|
|
858
897
|
computer-use cycles, scripted browser steps, and in-sandbox terminal-agent exec
|
|
859
898
|
output all map onto one `ActorTrace`. Registered actors live in
|
|
860
899
|
`src/actors/registry.ts` (`codex-app-server`, `openai-computer-use`,
|
|
861
|
-
`local-agent`, `scripted-browser`, `codex-exec`). A
|
|
900
|
+
`local-agent`, `scripted-browser`, `codex-exec`). A study that names
|
|
862
901
|
`pi-agent-core` or `claude-agent-sdk` fails to parse. There is no
|
|
863
902
|
`humanish.actor.v1`; that name never shipped.
|
|
864
903
|
|
|
@@ -870,7 +909,7 @@ Core-owned fields:
|
|
|
870
909
|
`terminal-exec`)
|
|
871
910
|
- `lane` (`code` | `computer-use` | `scripted-browser` | `terminal`)
|
|
872
911
|
- `persona` (`id`, `traitsApplied`, `promptDigest`)
|
|
873
|
-
- `capabilities.keyPlacement` (`external` | `in-sandbox-command-scoped`):
|
|
912
|
+
- `capabilities.keyPlacement` (`external` | `in-sandbox-command-scoped`): where
|
|
874
913
|
the actor's runtime key lives. It is registry metadata the engine enforces. The
|
|
875
914
|
terminal agent declares `in-sandbox-command-scoped` (the agent-under-test runs
|
|
876
915
|
inside the sandbox); every other actor is `external` (absent === external).
|
|
@@ -881,7 +920,7 @@ Core-owned fields:
|
|
|
881
920
|
meaning the subject failed the script while the harness executed faithfully; and
|
|
882
921
|
`budget_reached`: a computer-use session ended by a limit. The loop
|
|
883
922
|
(`src/actors/computer-use/loop/ending.ts`) emits it when the time budget runs
|
|
884
|
-
out after at least one material action, when `
|
|
923
|
+
out after at least one material action, when `caps.maxUsd` or the
|
|
885
924
|
study's shared spend threshold is crossed, when the adapter reports a local
|
|
886
925
|
admission limit, or when the provider hits its output or context token limit.
|
|
887
926
|
Every `budget_reached` session has status `incomplete`
|
|
@@ -893,24 +932,24 @@ Core-owned fields:
|
|
|
893
932
|
may carry `cacheWriteInput` (tokens billed at the provider's cache-write rate,
|
|
894
933
|
OpenAI 5.6+) and `turns[]` (per provider-request usage, the recorded fact
|
|
895
934
|
long-context tier pricing needs). Both are additive and absent on
|
|
896
|
-
producers that do not report them
|
|
935
|
+
producers that do not report them. Items may
|
|
897
936
|
carry `at` (ISO-8601 recording stamp from the loop's clock) and, on
|
|
898
|
-
click-like `ui_action` items, structured `coord` (`x`/`y`). Both are additive
|
|
899
|
-
|
|
937
|
+
click-like `ui_action` items, structured `coord` (`x`/`y`). Both are additive:
|
|
938
|
+
absent on older bundles and non-stamping producers, and absence means
|
|
900
939
|
"timing/position unrecorded", never zero
|
|
901
|
-
- optional `modelSettings` (`humanish.model-settings.v1
|
|
940
|
+
- optional `modelSettings` (`humanish.model-settings.v1`): how the model was
|
|
902
941
|
asked to run, alongside `ids.model` which says which model it was.
|
|
903
|
-
`reasoningEffort` records the value the request
|
|
904
|
-
including the provider default when a
|
|
942
|
+
`reasoningEffort` records the value the request actually carried,
|
|
943
|
+
including the provider default when a study declared nothing. The resolved
|
|
905
944
|
value is what produced the trace, and recording "unset" would misdescribe
|
|
906
945
|
the run. Absent when a provider declares no settings and on every
|
|
907
946
|
pre-existing bundle; tolerated by verify. It exists because effort was
|
|
908
|
-
unreachable from a
|
|
909
|
-
is part of
|
|
947
|
+
unreachable from a study, which made every run take the default silently. Effort
|
|
948
|
+
is part of who the participant was rather than of how the instrument was tuned
|
|
910
949
|
(docs/principles/actor-fidelity.md), so a trace without it is a result missing
|
|
911
950
|
half its sample description
|
|
912
951
|
- optional `modelSettings.maxOutputTokens`: the declared positive integer
|
|
913
|
-
`
|
|
952
|
+
`actor.maxOutputTokens`, passed to every first-party OpenAI CUA response
|
|
914
953
|
request, including reasoning output. Absent when undeclared. The first request
|
|
915
954
|
of a session and closing reports use `min(maxOutputTokens, 1024)`, or 1024 when
|
|
916
955
|
undeclared; the first request also carries the opening screenshot as an
|
|
@@ -923,17 +962,37 @@ Core-owned fields:
|
|
|
923
962
|
“provider reply cut off by the output limit; asking again” notice. A second
|
|
924
963
|
cut-off reply to the same request ends the session with
|
|
925
964
|
`stopCause: provider_output_limit`.
|
|
926
|
-
- optional `
|
|
965
|
+
- optional `conversation`: how the first-party OpenAI computer-use provider
|
|
966
|
+
carried the conversation between requests. `mode` is `threaded` (the server
|
|
967
|
+
kept it through `previous_response_id`) or `explicit_context` (the server kept
|
|
968
|
+
none). `explicitReason` says why: `configured` (`zeroDataRetention`) or
|
|
969
|
+
`zdr_rejection` (the organization rejected server-side state; `switchedAt` and
|
|
970
|
+
`switchedAtRequest` say when). In `explicit_context` each request carries the
|
|
971
|
+
conversation from the client, with `store: false` and the reasoning returned
|
|
972
|
+
in encrypted form. It carries the opening message, every exchange of a reply
|
|
973
|
+
with the outputs that answered it, and the latest reply. Past an estimated
|
|
974
|
+
64,000 input tokens the opening screenshot is dropped first, then the oldest
|
|
975
|
+
exchanges become lines of a note, sent as an assistant message, that keeps
|
|
976
|
+
their reasoning summaries, messages and actions as text. The two newest
|
|
977
|
+
exchanges are always carried whole, even when they alone pass the budget. `summarizedTurns` counts the earlier exchanges the latest
|
|
978
|
+
`explicit_context` request no longer carried whole: lines of the note, or
|
|
979
|
+
only counted once the note reached its cap.
|
|
980
|
+
`requests[]` has one entry per participant request: its `mode` and, in
|
|
981
|
+
`explicit_context`, `carriedExchanges`, `carriedScreenshots` and
|
|
982
|
+
`estimatedInputTokens`. Billed input per request is in `tokenUsage.turns`. A
|
|
983
|
+
participant that ran in `explicit_context` gets a run warning. Absent on other
|
|
984
|
+
providers and on earlier bundles
|
|
985
|
+
- optional `affordanceUse` (`humanish.affordance-use.v1`): which kind of route this
|
|
927
986
|
actor took (see Affordance Use below)
|
|
928
987
|
- optional `estimatedCost` (`humanish.actor-estimated-cost.v1`): a token-derived
|
|
929
|
-
cost
|
|
930
|
-
It is deliberately a
|
|
931
|
-
`costUsd` is
|
|
932
|
-
`estimatedCost.estimatedCostUsd` is a rate-table multiply, named
|
|
933
|
-
|
|
988
|
+
cost estimate for this participant (see Run Cost Summary And Estimated Actor Cost).
|
|
989
|
+
It is deliberately a different field from `tokenUsage.costUsd`: a bare
|
|
990
|
+
`costUsd` is reserved for a real provider-returned charge, while
|
|
991
|
+
`estimatedCost.estimatedCostUsd` is a rate-table multiply, named as an
|
|
992
|
+
estimate so a reader can never confuse the two. Absent on
|
|
934
993
|
the Codex app-server and scripted routes and on every pre-existing bundle; the
|
|
935
994
|
terminal route records a `null` estimate. A `null`
|
|
936
|
-
`estimatedCostUsd` is
|
|
995
|
+
`estimatedCostUsd` is declared absent (unknown rate / no usage), never 0.
|
|
937
996
|
|
|
938
997
|
Unexpected actor-loop diagnostics live inside `items[]` as
|
|
939
998
|
`kind: notice`, `status: error` rows. They are public-safe evidence, not crash
|
|
@@ -976,12 +1035,12 @@ items: []
|
|
|
976
1035
|
|
|
977
1036
|
Reserved: `humanish.substrate.v1` is named here for layering intent but has
|
|
978
1037
|
never shipped; no code emits or validates it. Substrate truth today lives
|
|
979
|
-
inside run bundles (per-stream transport and status) and
|
|
1038
|
+
inside run bundles (per-stream transport and status) and study execution config
|
|
980
1039
|
(`execution.target: local | e2b-desktop | e2b-terminal`). Do not emit this schema.
|
|
981
1040
|
|
|
982
1041
|
## Serve Result And Reserved Control-Plane Namespace
|
|
983
1042
|
|
|
984
|
-
`humanish
|
|
1043
|
+
`humanish observe --all` reports `humanish.serve-result.v1`. The exported `ServeResult`
|
|
985
1044
|
type and `SERVE_SCHEMA` constant in `src/observer/serve.ts` are authoritative:
|
|
986
1045
|
mode (`loopback | exposed | share-safe-open`), the loopback host/port,
|
|
987
1046
|
`publicUrl`, the `tunnel` provider/url, an `oauth` echo (`provider`,
|
|
@@ -1022,10 +1081,10 @@ discipline** that distinguishes three states and never conflates them:
|
|
|
1022
1081
|
- `usd: null` is **not measured**: no spend signal exists for the category on
|
|
1023
1082
|
this run. `null` is written explicitly (never `undefined`-omitted, never guessed
|
|
1024
1083
|
to `0`). A line with `null` says "this category exists but we did not measure
|
|
1025
|
-
it"; the no-spend proof reports it as unmeasured and does
|
|
1084
|
+
it"; the no-spend proof reports it as unmeasured and does not claim it is zero.
|
|
1026
1085
|
- an **absent** line is **not applicable** (n/a) to the participant or run.
|
|
1027
1086
|
|
|
1028
|
-
`knownTotalUsd` sums
|
|
1087
|
+
`knownTotalUsd` sums only the non-null lines (a `null` line contributes nothing
|
|
1029
1088
|
and is never coerced to `0`); `fullyMeasured` is true only when no line is null.
|
|
1030
1089
|
Core meters only the `provider` line, populated from the actor trace's
|
|
1031
1090
|
`tokenUsage.costUsd` when present (else `null`); `product`/`media`/`payment`
|
|
@@ -1034,7 +1093,7 @@ cost-probe seam. The terminal route records the model as `codex` and does not pi
|
|
|
1034
1093
|
model, so a measured token count stays `usd: null` with `source: unpriced-token-usage`, and
|
|
1035
1094
|
`knownTotalUsd: 0` with `fullyMeasured: false` means no line of this ledger was priced. E2B
|
|
1036
1095
|
time for the terminal sandbox is not a line of this ledger, whose lines are checked against
|
|
1037
|
-
`
|
|
1096
|
+
`caps.maxUsd`. The run bundle's `cost` summary prices it as a `desktop-minutes`
|
|
1038
1097
|
line (see Run Cost Summary And Estimated Actor Cost below).
|
|
1039
1098
|
|
|
1040
1099
|
```yaml
|
|
@@ -1049,10 +1108,10 @@ knownTotalUsd: 0
|
|
|
1049
1108
|
fullyMeasured: false
|
|
1050
1109
|
```
|
|
1051
1110
|
|
|
1052
|
-
The no-spend proof (`humanish.terminal-no-spend-proof.v1`) is
|
|
1111
|
+
The no-spend proof (`humanish.terminal-no-spend-proof.v1`) is derived from the
|
|
1053
1112
|
ledger. It vouches only for what it measured: `knownZeroLines` (proven zero),
|
|
1054
1113
|
`knownNonZeroLines` (break `satisfied`), and `unmeasuredLines` (the `null` lines
|
|
1055
|
-
it explicitly
|
|
1114
|
+
it explicitly cannot vouch for). `satisfied` is true only when every known line
|
|
1056
1115
|
is within `maxUsd` (for a no-spend run, `maxUsd: 0` ⇒ every known line is `0`).
|
|
1057
1116
|
Unmeasured lines never break it, so a ledger whose lines are all `null` is
|
|
1058
1117
|
`satisfied` with nothing proven. The `statement` says which case applies: it
|
|
@@ -1072,9 +1131,9 @@ knownTotalUsd: 0
|
|
|
1072
1131
|
statement: "No-spend proof not established for maxUsd=0: no spend line was measured. …"
|
|
1073
1132
|
```
|
|
1074
1133
|
|
|
1075
|
-
**Full caps enforcement (fail-closed, not advisory).** `
|
|
1076
|
-
is enforced against the ledger: if the observed
|
|
1077
|
-
run fails closed (`
|
|
1134
|
+
**Full caps enforcement (fail-closed, not advisory).** `caps.maxUsd`
|
|
1135
|
+
is enforced against the ledger: if the observed known spend exceeds `maxUsd`, the
|
|
1136
|
+
run fails closed (`HUMANISH_TERMINAL_CAPS_EXCEEDED`); `maxJobs` likewise when
|
|
1078
1137
|
a known job count is present; `maxMinutes` is the wall-clock kill (unchanged).
|
|
1079
1138
|
Unknowns (`null`) never trip a cap (we cannot claim a violation we did not
|
|
1080
1139
|
measure) and never grant a green pass (they surface as unmeasured). `verifyRun`
|
|
@@ -1084,12 +1143,13 @@ proof claims zero on a `null` line, or when known spend exceeds the declared cap
|
|
|
1084
1143
|
## Run Status (identity + liveness index)
|
|
1085
1144
|
|
|
1086
1145
|
`humanish.run-status.v1` is `status.json`, written inside each run directory by
|
|
1087
|
-
every
|
|
1146
|
+
every route at run start, refreshed on a fixed cadence while the run is
|
|
1088
1147
|
alive, and finalized when it ends: `{ schema, runId, state: running |
|
|
1089
|
-
finished | interrupted, mode,
|
|
1090
|
-
signal?, outcome? }`.
|
|
1091
|
-
`
|
|
1092
|
-
|
|
1148
|
+
finished | interrupted, mode, study?, pid, startedAt, updatedAt, completedAt?,
|
|
1149
|
+
signal?, outcome? }`. A record written by 0.108 or earlier also has `lab`, with the same value as
|
|
1150
|
+
`study`, and readers accept it.
|
|
1151
|
+
`outcome` carries the bundle's `verdict`, `participants`, `estimatedCostUsd` and
|
|
1152
|
+
`estimatedCostComplete` when the run finishes, then the result's `ok` and `execution: { succeeded,
|
|
1093
1153
|
failures: [{ kind, message }], warnings? }` once the Observer has rendered. The
|
|
1094
1154
|
verdict is what the participants experienced; `execution` is whether the run
|
|
1095
1155
|
worked as an execution (`kind` is `harness`, `provider-cleanup`,
|
|
@@ -1109,6 +1169,11 @@ the participant (or `subject`), the release warning and the
|
|
|
1109
1169
|
`humanish reclaim --run <id>` command. A local VM writes no receipt, so its
|
|
1110
1170
|
entry names the container and the `docker rm --force --volumes <container>`
|
|
1111
1171
|
command that removes it (through `limactl shell` on a Mac).
|
|
1172
|
+
`estimatedCostUsd` is the participants-and-desktops estimate and excludes
|
|
1173
|
+
analysis. `estimatedCostComplete` is the bundle's `cost.fullyEstimated`, written
|
|
1174
|
+
with it at publish: false means some participant or desktop usage has no price
|
|
1175
|
+
and the estimate is a lower bound. A record without it, as every record before
|
|
1176
|
+
0.109, says nothing about completeness, and readers treat it as unknown.
|
|
1112
1177
|
|
|
1113
1178
|
`interrupted` with `signal` (`SIGINT`, `SIGTERM` or `SIGHUP`) is written by
|
|
1114
1179
|
the CLI's run command when that signal stops a live run outside post-run
|
|
@@ -1116,26 +1181,26 @@ analysis. It then kills the E2B sandboxes the run's `sandbox-receipts.ndjson`
|
|
|
1116
1181
|
names, writes `reclaim-receipt.json` as `humanish reclaim` does, and exits
|
|
1117
1182
|
128+n. The bundle is not finished: run.json keeps its last live flush, and no
|
|
1118
1183
|
`outcome` is written. A `running` record that stopped refreshing still reads as
|
|
1119
|
-
interrupted once stale. A library caller of `
|
|
1184
|
+
interrupted once stale. A library caller of `runStudy` gets no signal handling. A
|
|
1120
1185
|
humanish older than this field rejects the state and falls back to the bundle's
|
|
1121
1186
|
own liveness.
|
|
1122
1187
|
|
|
1123
|
-
It answers two questions the filesystem could not answer before: **which
|
|
1188
|
+
It answers two questions the filesystem could not answer before: **which study**
|
|
1124
1189
|
a run belongs to, and **whether it is still alive**, including for runs an
|
|
1125
|
-
agent launched (`
|
|
1190
|
+
agent launched (`run --json`) or that were detached, which previously wrote
|
|
1126
1191
|
nothing at all until they completed.
|
|
1127
1192
|
|
|
1128
|
-
It is a
|
|
1193
|
+
It is a derived index, not evidence. `run.json` remains the evidence-of-record;
|
|
1129
1194
|
`verify` never gates on `status.json`, nothing in it is a claim about what a
|
|
1130
1195
|
participant did, and when the two disagree the bundle wins and the record is
|
|
1131
1196
|
rebuildable from it. A `running` record whose `updatedAt` is older than three
|
|
1132
|
-
touch intervals is
|
|
1197
|
+
touch intervals is interrupted, not alive. A dropped connection or a killed
|
|
1133
1198
|
terminal leaves exactly that shape, so the record reads as interrupted
|
|
1134
1199
|
(`classifyRunStatus` is the one shared definition). Fields are
|
|
1135
1200
|
public-safe by construction: no hostname and no user paths, because a run
|
|
1136
1201
|
directory may be shared.
|
|
1137
1202
|
|
|
1138
|
-
## Run Index, Run Detail, And The Terminal Surface
|
|
1203
|
+
## Run Index, Run Detail, And The Terminal Surface
|
|
1139
1204
|
|
|
1140
1205
|
Three derived projections that exist so a surface can list, classify and watch
|
|
1141
1206
|
runs without opening evidence for all of them. None is authoritative: `run.json`
|
|
@@ -1145,17 +1210,26 @@ them is a claim about what a participant did.
|
|
|
1145
1210
|
`humanish.run-index.v1` is the listing projection. One entry per run, read
|
|
1146
1211
|
cheapest-source-first: the `status.json` record, else the bundle, else the run
|
|
1147
1212
|
directory alone. `{ runId, derivedFrom: status | bundle | directory, liveness,
|
|
1148
|
-
mode?, pid?,
|
|
1149
|
-
participants?, estimatedCostUsd?,
|
|
1213
|
+
mode?, pid?, study?, startedAt?, updatedAt?, completedAt?, verdict?,
|
|
1214
|
+
participants?, estimatedCostUsd?, estimatedCostComplete?, analysisCost?,
|
|
1215
|
+
durationMs? }`. The point is cost: walking
|
|
1150
1216
|
every run tree and parsing every bundle measured 167ms on a 25-run project,
|
|
1151
1217
|
against 16ms cold and 2.8ms warm here, which is what makes a surface that
|
|
1152
1218
|
refreshes on a cadence affordable. `derivedFrom` is reported so a surprising row
|
|
1153
1219
|
can be traced to the file it came from. A run with receipts and no outcome is
|
|
1154
1220
|
`interrupted` (the shape a dropped connection leaves), and so is an
|
|
1155
|
-
|
|
1221
|
+
in-progress bundle reached without a status record: there is no freshness to
|
|
1156
1222
|
judge, and nothing in it says the run finished.
|
|
1157
1223
|
|
|
1158
|
-
`
|
|
1224
|
+
`estimatedCostUsd` is the participants-and-desktops figure from the status
|
|
1225
|
+
record or bundle and excludes analysis. `estimatedCostComplete` says whether that
|
|
1226
|
+
figure is whole, and is absent when the record does not say. `analysisCost`
|
|
1227
|
+
covers the analysis: `{ requests, estimatedUsd, complete, providers }` for every
|
|
1228
|
+
analysis attempt the run sent, read by the same reader as `humanish stats`, and
|
|
1229
|
+
absent when the run sent none. Analysis is written after the status record, so
|
|
1230
|
+
`analysisCost` is cached on a fingerprint of the run's analysis directories.
|
|
1231
|
+
|
|
1232
|
+
`humanish.run-detail.v1` is the watching projection, for one run. Who is in it
|
|
1159
1233
|
and what they are thinking: `{ runId, participants: [{ id, label, personaId?,
|
|
1160
1234
|
traits, status?, completionReason?, thought?, turns?, actions?, thoughts?,
|
|
1161
1235
|
estimatedCostUsd? }], observerPath?, automaticAnalysis? }`. It reads the actor trace from
|
|
@@ -1163,7 +1237,7 @@ estimatedCostUsd? }], observerPath?, automaticAnalysis? }`. It reads the actor t
|
|
|
1163
1237
|
finished, preferring the live one, so a single screen renders a run the whole
|
|
1164
1238
|
way through. A reasoning item still being written is skipped rather than quoted
|
|
1165
1239
|
half-finished, and the text is carried verbatim: a surface may wrap it, and
|
|
1166
|
-
nothing paraphrases it. Unlike the index this
|
|
1240
|
+
nothing paraphrases it. Unlike the index this does open the bundle, which is affordable
|
|
1167
1241
|
only because it is asked for the one run being watched.
|
|
1168
1242
|
|
|
1169
1243
|
`humanish.tui-result.v1` is what `humanish tui` emits when it refuses:
|
|
@@ -1172,23 +1246,23 @@ only because it is asked for the one run being watched.
|
|
|
1172
1246
|
`HUMANISH_TUI_BUNDLE_MISSING`. `HUMANISH_TUI_AGENT_SESSION` is the one a TTY
|
|
1173
1247
|
check could not catch: `codex exec` allocates a PTY for the commands it runs, so
|
|
1174
1248
|
both streams are terminals and the surface used to open. A study watched an
|
|
1175
|
-
agent move through the
|
|
1176
|
-
(humanish/
|
|
1249
|
+
agent move through the studies list and start a run it did not mean to start
|
|
1250
|
+
(humanish/studies/handed-a-human-surface.yaml). The refusal names the environment variable
|
|
1177
1251
|
that identified the runner, so the reader can check the claim, and `--force` is
|
|
1178
1252
|
the escape for a person who really is at that keyboard. Every other
|
|
1179
1253
|
command is built for an agent to drive; this one takes the screen and waits for
|
|
1180
1254
|
a person, so a non-interactive stdin or stdout fails closed naming the commands
|
|
1181
|
-
that
|
|
1255
|
+
that do answer the question rather than rendering escape codes into a pipe.
|
|
1182
1256
|
|
|
1183
1257
|
## Run Cost Summary And Estimated Actor Cost
|
|
1184
1258
|
|
|
1185
|
-
The computer-use (CUA) route surfaces an
|
|
1259
|
+
The computer-use (CUA) route surfaces an advisory, additive cost estimate. It is
|
|
1186
1260
|
never authoritative: every dollar figure is a rate-table multiply, labeled
|
|
1187
|
-
"estimated (rates as of `<date>`)", and is
|
|
1188
|
-
|
|
1261
|
+
"estimated (rates as of `<date>`)", and is never presented as a provider charge.
|
|
1262
|
+
Three new `.v1` schema tags ship, all additive and optional so
|
|
1189
1263
|
`humanish.run-bundle.v1` stays v1 and every pre-existing bundle is byte-stable:
|
|
1190
1264
|
|
|
1191
|
-
- `humanish.pricing.v1`: the
|
|
1265
|
+
- `humanish.pricing.v1`: the operator-editable rate table in `src/run/pricing.ts`:
|
|
1192
1266
|
dated per-model input/output USD-per-token rates and E2B CPU/GiB-second
|
|
1193
1267
|
rates, each with a public pricing-page `source` and an `asOf`
|
|
1194
1268
|
date. A prominent banner says these are estimates to update when providers
|
|
@@ -1198,9 +1272,9 @@ never authoritative: every dollar figure is a rate-table multiply, labeled
|
|
|
1198
1272
|
request; priced exactly only from the trace's per-request `turns` ledger;
|
|
1199
1273
|
totals alone never re-tier, which errs toward under-estimating). Some
|
|
1200
1274
|
entries are `placeholder: true` stand-ins (the legacy desktop helper's
|
|
1201
|
-
8-vCPU/8-GiB planning assumption); an operator
|
|
1275
|
+
8-vCPU/8-GiB planning assumption); an operator must confirm them before trusting
|
|
1202
1276
|
the magnitude; the flag propagates into every estimate so a stand-in is never
|
|
1203
|
-
mistaken for a live rate. An
|
|
1277
|
+
mistaken for a live rate. An unknown model/desktop rate is declared absent
|
|
1204
1278
|
(`estimatedCostUsd: null` + a `reason`), never guessed.
|
|
1205
1279
|
- `humanish.actor-estimated-cost.v1` (`ActorTrace.estimatedCost`): one participant's
|
|
1206
1280
|
token-derived model cost, with `estimatedCostUsd` (or `null` + `reason`
|
|
@@ -1209,7 +1283,7 @@ never authoritative: every dollar figure is a rate-table multiply, labeled
|
|
|
1209
1283
|
arrived as turn totals, such as Codex `turn.completed`, priced at the base tier because no single
|
|
1210
1284
|
request's size is known; the run summary's `model-tokens` line carries the same `basis`.
|
|
1211
1285
|
- `humanish.run-cost-summary.v1` (`RunBundle.cost`): the sum of every participant's
|
|
1212
|
-
`model-tokens` lines
|
|
1286
|
+
`model-tokens` lines plus `desktop-minutes` lines. New independent CUA runs
|
|
1213
1287
|
price each owned desktop separately; concurrent shared-world runs add one line per participant
|
|
1214
1288
|
and a `laneId: subject` desktop line for a provisioned plane; older single aggregate
|
|
1215
1289
|
lines remain readable.
|
|
@@ -1222,23 +1296,23 @@ never authoritative: every dollar figure is a rate-table multiply, labeled
|
|
|
1222
1296
|
Live terminal-product runs emit the same summary: one `desktop-minutes` line for
|
|
1223
1297
|
the E2B shell sandbox (its acquired-to-cleanup span and `e2b.getInfo` size) and
|
|
1224
1298
|
one `model-tokens` line for the Codex participant, priced from the model the route passed
|
|
1225
|
-
to Codex (`gpt-5.6-sol` unless the
|
|
1299
|
+
to Codex (`gpt-5.6-sol` unless the study declares one) with `basis:
|
|
1226
1300
|
aggregated_turns_base_rate`, or `null` with `no_token_usage`. Older terminal bundles record
|
|
1227
1301
|
`no_rate_for_model` (model `codex`). The terminal trace records the same `estimatedCost`. The sandbox line is not part of the
|
|
1228
|
-
terminal cost ledger, whose lines are checked against `
|
|
1302
|
+
terminal cost ledger, whose lines are checked against `caps.maxUsd`.
|
|
1229
1303
|
|
|
1230
|
-
The summary follows the
|
|
1231
|
-
`estimatedTotalUsd` sums
|
|
1232
|
-
|
|
1304
|
+
The summary follows the same null discipline as the terminal cost ledger above.
|
|
1305
|
+
`estimatedTotalUsd` sums only the non-null `breakdown` lines and is `null` iff
|
|
1306
|
+
every line is null (never coerced to `0`); a present-but-unpriceable line stays
|
|
1233
1307
|
in `breakdown` with `estimatedCostUsd: null` + a `reason` (it records that we
|
|
1234
1308
|
tried and could not price it) and contributes nothing. `fullyEstimated` is
|
|
1235
1309
|
`false` when any applicable line is null (the total is then a lower bound). A spend-free
|
|
1236
1310
|
live run has no lines and records `estimatedTotalUsd: 0` with `ratesAsOf: null`; verify
|
|
1237
1311
|
asks for a rates date only when a line is priced.
|
|
1238
1312
|
`placeholder` is true when any contributing rate is a stand-in; `ratesAsOf` is
|
|
1239
|
-
the
|
|
1240
|
-
as its stalest input, so
|
|
1241
|
-
keeps its own true `asOf`). `desktopMinutes` is a
|
|
1313
|
+
the min (oldest) `asOf` across contributing rates. An aggregate is only as fresh
|
|
1314
|
+
as its stalest input, so max would overclaim freshness (each `breakdown` line
|
|
1315
|
+
keeps its own true `asOf`). `desktopMinutes` is a host-side
|
|
1242
1316
|
acquired-handle→cleanup span, excluding allocation/startup before handle acquisition.
|
|
1243
1317
|
It approximates E2B's server-side billed lifetime. Plan fees, credits, and negotiated
|
|
1244
1318
|
prices are excluded; unknown remaining lifetime makes `fullyEstimated` false.
|
|
@@ -1272,17 +1346,17 @@ desktopMinutes: 1
|
|
|
1272
1346
|
note: "Estimated 11.60167 USD total…"
|
|
1273
1347
|
```
|
|
1274
1348
|
|
|
1275
|
-
`verifyRun` asserts
|
|
1349
|
+
`verifyRun` asserts labeling and provenance, never magnitude. Absence passes
|
|
1276
1350
|
(fail-open on display): a bundle with no cost, a null estimate that carries a
|
|
1277
|
-
`reason` and a null `ratesAsOf`, or a participant without `estimatedCost` verifies fine. A
|
|
1351
|
+
`reason` and a null `ratesAsOf`, or a participant without `estimatedCost` verifies fine. A claimed number fails closed when it lacks its
|
|
1278
1352
|
`ratesAsOf` date or `source`, or when `estimatedTotalUsd` does not equal the
|
|
1279
1353
|
rounded sum of its non-null lines (a null line coerced to 0 is a mechanism
|
|
1280
1354
|
mismatch). A correctly-labeled huge estimate still passes. Cost is neither a
|
|
1281
1355
|
secret nor a share-blocker: its magnitude never affects `shareSafety`. A labeling
|
|
1282
1356
|
failure fails verify, which blocks sharing like any other failed check.
|
|
1283
1357
|
|
|
1284
|
-
**Computer-use spend thresholds.** `
|
|
1285
|
-
to each participant. `
|
|
1358
|
+
**Computer-use spend thresholds.** `caps.maxUsd` applies independently
|
|
1359
|
+
to each participant. `caps.maxTotalUsd` shares an estimated model-spend ledger
|
|
1286
1360
|
across the study's participants. Either, both, or neither may be declared. Without a
|
|
1287
1361
|
shared threshold, N participants each have their own `maxUsd`; N × `maxUsd` is the sum
|
|
1288
1362
|
of those thresholds, not a guaranteed total spending ceiling.
|
|
@@ -1326,10 +1400,10 @@ threshold is not proof of task completion.
|
|
|
1326
1400
|
An absent threshold is uncapped. A zero threshold can still permit a paid model
|
|
1327
1401
|
request before reported usage trips it; `maxUsd: 0` is not a no-provider-call
|
|
1328
1402
|
mode. Use the keyless `humanish run first-run` preview or an explicit
|
|
1329
|
-
`humanish
|
|
1403
|
+
`humanish run <study> --dry-run` for a path without provider calls. A declared
|
|
1330
1404
|
threshold on a model `src/run/pricing.ts` cannot price is refused at preflight
|
|
1331
|
-
(`
|
|
1332
|
-
shared-world
|
|
1405
|
+
(`HUMANISH_COMPUTER_USE_UNPRICED_CAP`, or `HUMANISH_SHARED_WORLD_UNPRICED_CAP` on a
|
|
1406
|
+
shared-world study) before sandbox allocation. This rate-availability
|
|
1333
1407
|
check is separate from the post-response spend check.
|
|
1334
1408
|
|
|
1335
1409
|
Library callers can make a capped session stricter by composing it from the loop and the default
|
|
@@ -1370,19 +1444,19 @@ original interruption cause first, with any missing usage still recorded as
|
|
|
1370
1444
|
unknown.
|
|
1371
1445
|
|
|
1372
1446
|
These computer-use rules do not replace the terminal route's separate
|
|
1373
|
-
`
|
|
1447
|
+
`caps` cost-ledger and product-spend rules described above.
|
|
1374
1448
|
|
|
1375
1449
|
## Affordance Use
|
|
1376
1450
|
|
|
1377
|
-
`humanish.affordance-use.v1` (additive `ActorTrace.affordanceUse`) records
|
|
1378
|
-
|
|
1451
|
+
`humanish.affordance-use.v1` (additive `ActorTrace.affordanceUse`) records which
|
|
1452
|
+
kind of route an actor took, per dispatched action, as counts by class:
|
|
1379
1453
|
|
|
1380
1454
|
| Class | What it covers |
|
|
1381
1455
|
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
1382
1456
|
| `pointer` | click, double-click, drag, scroll: interaction with what is rendered |
|
|
1383
1457
|
| `keyboard` | typed text and key presses into the page |
|
|
1384
1458
|
| `speech` | spoken input from a `speak` action |
|
|
1385
|
-
| `url-navigation` | typing a URL (the `nav` subset); a
|
|
1459
|
+
| `url-navigation` | typing a URL (the `nav` subset); a human affordance, see below |
|
|
1386
1460
|
| `script-execution` | a `javascript:` or `data:` URL; not a human affordance |
|
|
1387
1461
|
| `devtools` | developer tooling opened by keyboard chord |
|
|
1388
1462
|
| `browser-internal` | `chrome://`, `about:`, `view-source:`, `devtools:`, `file:`, `edge:`, `brave:` (the browser, not the product) |
|
|
@@ -1393,45 +1467,48 @@ rate; `shortcutTotal` rolls up `script-execution` + `devtools` +
|
|
|
1393
1467
|
`browser-internal`, and a value of `0` is a meaningful result rather than an
|
|
1394
1468
|
absence.
|
|
1395
1469
|
|
|
1396
|
-
Direct URL navigation is deliberately its
|
|
1470
|
+
Direct URL navigation is deliberately its own class and is grouped with the
|
|
1397
1471
|
naturalistic classes, not with script execution: `load(url)` appears in 99.4% of
|
|
1398
1472
|
2,337 real human web demonstrations, so address-bar use is ordinary human
|
|
1399
1473
|
behavior and classifying it as a shortcut would make an ordinary human participant look
|
|
1400
1474
|
unfaithful. See [`docs/principles/actor-fidelity.md`](../principles/actor-fidelity.md)
|
|
1401
1475
|
for the evidence and the scoping of what a fidelity claim can mean.
|
|
1402
1476
|
|
|
1403
|
-
The record carries a
|
|
1477
|
+
The record carries a class and at most a scheme-shaped signal (`javascript:`,
|
|
1404
1478
|
`https:`, a devtools chord), never the typed text, which can be a password, a
|
|
1405
1479
|
session token, or an identifying URL path. Classification runs at dispatch
|
|
1406
1480
|
because the text exists only there: the trace's own action label deliberately
|
|
1407
1481
|
renders `type [N chars]`.
|
|
1408
1482
|
|
|
1409
|
-
The harness states
|
|
1483
|
+
The harness states no verdict about a class. Whether an affordance invalidates a
|
|
1410
1484
|
study depends on the population that study declares, which is product semantics
|
|
1411
1485
|
and belongs to the adopter's scorer. That scorer already receives the full trace,
|
|
1412
1486
|
so `affordanceUse` needs no extra wiring to reach it. Present on computer-use participants
|
|
1413
1487
|
that dispatched at least one action; absent elsewhere and on every pre-existing
|
|
1414
1488
|
bundle, and its absence is tolerated by verify.
|
|
1415
1489
|
|
|
1416
|
-
## Library options
|
|
1417
|
-
|
|
1418
|
-
`
|
|
1419
|
-
refusal comes back in the route's own result envelope, with no run directory, receipt or
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
|
1425
|
-
|
|
|
1426
|
-
| `
|
|
1427
|
-
| `
|
|
1428
|
-
| `
|
|
1429
|
-
| `
|
|
1430
|
-
| `
|
|
1431
|
-
| `
|
|
1432
|
-
| `
|
|
1433
|
-
|
|
1434
|
-
`
|
|
1490
|
+
## Library options
|
|
1491
|
+
|
|
1492
|
+
`runStudy(config, options)` checks its `RunStudyOptions` against the study's route before anything
|
|
1493
|
+
runs. A refusal comes back in the route's own result envelope, with no run directory, receipt or
|
|
1494
|
+
sandbox. 0.109.0 removed the 0.107 names (`runLab`, `RunLabOptions`, `parseLabConfig`,
|
|
1495
|
+
`LAB_CONFIG_SCHEMA`, `LabConfig`, the `Lab*` result and event types, the nine `Cua*` loop types,
|
|
1496
|
+
`CuaAdmissionLimitError` and `BrowserLabScoringContext`), which 0.108.0 kept as deprecated aliases.
|
|
1497
|
+
|
|
1498
|
+
| Option | What it does | Routes |
|
|
1499
|
+
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1500
|
+
| `env` | Keys and subject env for the run. Defaults to `process.env` | all |
|
|
1501
|
+
| `scorer` | An `AdapterScorerModule` (`score`, `deriveFeedback`, and `deriveArtifacts` on browser routes) over the finished evidence. A scorer written for one context passes through `browserScorer` or `terminalScorer` | computer use, shared world, terminal |
|
|
1502
|
+
| `createProvider(ctx)` | The participant's brain. `ctx` is `ProviderContext`: `config`, `participant { id, index, count }` and `executor` | computer use: E2B, local VM or in process |
|
|
1503
|
+
| `inProcess.executor({ config, appUrl })` | Drives an `app-url` or `local-app` subject in process, one participant. Requires `createProvider` | computer use |
|
|
1504
|
+
| `prepareDesktop(desktop, target)` | Runs on an E2B sandbox before provisioning. `target` is `{ kind: "subject" }` or `{ kind: "participant", participant }` | computer use on E2B (each participant); shared world (provisioned: the subject, then each participant; external-public: each participant); scripted clone (the subject) |
|
|
1505
|
+
| `onEvent(event)` | Observes `StudyEvent`s, below | all |
|
|
1506
|
+
| `onStream(event)` | Awaited. `ready` after a participant's live stream starts; its `url` carries an auth key and must never be persisted. `ended` after the participant's sandbox is gone. A rejected `ready` becomes a run warning; an `ended` rejection is swallowed. Each event carries `participantId`, `recordId` (the id of this participant's entry in `run.json` `simulations[]`, such as `sim-001`, which `streams[].simId` also holds) and `streamId`; `ready` adds `sandboxId` and `url`. 0.109.0 removed `simId`, the older name for `recordId`. | computer use and shared world on E2B |
|
|
1507
|
+
| `analysisSignal` | Cancels post-run analysis only | routes with post-run analysis |
|
|
1508
|
+
| `onObserverReady(observer)` | Awaited before any participant desktop exists | live computer use; live shared world, where the provisioned subject sandbox is already billed |
|
|
1509
|
+
| `rerun.participantIds` | Participants to rerun from `rerun.sourceRunId` | computer use |
|
|
1510
|
+
|
|
1511
|
+
`StudyEvent` has four types:
|
|
1435
1512
|
|
|
1436
1513
|
- `plan`: the participants (`id`, `persona`, `device`, `instructionDigest`) before any sandbox
|
|
1437
1514
|
or provider call. Computer use only; the other routes gain it later.
|
|
@@ -1446,17 +1523,17 @@ throw or a rejected promise becomes a redacted run warning.
|
|
|
1446
1523
|
|
|
1447
1524
|
Refusals:
|
|
1448
1525
|
|
|
1449
|
-
- `
|
|
1450
|
-
a preview or scripted
|
|
1526
|
+
- `HUMANISH_STUDY_OPTION_UNSUPPORTED`: the route cannot honor the option, for example `scorer` on
|
|
1527
|
+
a preview or scripted study, `createProvider` off computer use, or `prepareDesktop` where no E2B
|
|
1451
1528
|
desktop exists. The message names the option and the route. The same code refuses a field
|
|
1452
|
-
`
|
|
1529
|
+
`RunStudyOptions` no longer has (below); that message names the field and where its job went.
|
|
1453
1530
|
|
|
1454
1531
|
`rerun.laneIds`, the older name of `rerun.participantIds`, was removed in 0.107.0. A caller that
|
|
1455
|
-
still passes it is refused with `
|
|
1532
|
+
still passes it is refused with `HUMANISH_STUDY_OPTION_UNSUPPORTED`; use `rerun.participantIds`.
|
|
1456
1533
|
|
|
1457
1534
|
The route hook bags (`cuaHooks`, `scriptedHooks`, `terminalHooks`, `sharedWorldHooks`,
|
|
1458
|
-
`automaticAnalysis`) were removed from `
|
|
1459
|
-
runners that took them (`
|
|
1535
|
+
`automaticAnalysis`) were removed from `RunStudyOptions`, with the hook bag types and the four route
|
|
1536
|
+
runners that took them (`runCuaActorStudy`, `runScriptedBrowserStudy`, `runTerminalProductStudy`,
|
|
1460
1537
|
`runConcurrentSharedWorld`). `lab` and `scorerProvenance` are set only by the humanish CLI. A
|
|
1461
1538
|
JavaScript caller that passes any of these fields is refused before anything runs. Where each
|
|
1462
1539
|
bag field's job went:
|
|
@@ -1481,25 +1558,25 @@ route-specific verdict rules in the next section.
|
|
|
1481
1558
|
0.107.0 also removed these exports from `humanish`. A removed function no longer warns; an import
|
|
1482
1559
|
of it fails.
|
|
1483
1560
|
|
|
1484
|
-
| Removed export | Use
|
|
1485
|
-
| ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1486
|
-
| `runDryRun`, `RunOptions`, `RunResult` | `
|
|
1487
|
-
| `runCuaActorSession` | `runComputerUseLoop` with `createOpenAiResponsesProvider({ singleDispatch: true })`, `redaction: defaultRedactionHooks` and `now: Date.now`, which `runCuaActorSession` defaulted (the composition above). A caller that passed `desktop` and `executorOptions` writes its own `
|
|
1488
|
-
| `
|
|
1489
|
-
| `SubjectPhaseEvent` | the `subject-phase` `
|
|
1490
|
-
| `
|
|
1491
|
-
| `selectLabBackend`, the `routesTo*` predicates, `actorResolvesToTerminal` | `routeOf(config)`
|
|
1492
|
-
| `
|
|
1493
|
-
| `cuaLaneCount` | the `plan` `
|
|
1494
|
-
| `resolveSeatUrl` | `
|
|
1495
|
-
| `cuaLaneValidationReason`, `sharedWorldValidationReason`, `concurrentSharedWorldValidationReason`, `externalPublicSharedWorldValidationReason` | `
|
|
1496
|
-
| `MAX_CUA_LANES` | none; `
|
|
1561
|
+
| Removed export | Use |
|
|
1562
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1563
|
+
| `runDryRun`, `RunOptions`, `RunResult` | `runStudy(config, options)` on a `this-repo` study; its result is `StudyResult<"preview">` |
|
|
1564
|
+
| `runCuaActorSession` | `runComputerUseLoop` with `createOpenAiResponsesProvider({ singleDispatch: true })`, `redaction: defaultRedactionHooks` and `now: Date.now`, which `runCuaActorSession` defaulted (the composition above). A caller that passed `desktop` and `executorOptions` writes its own `ComputerUseExecutor`: the E2B desktop executor is not exported |
|
|
1565
|
+
| `CuaActorStudyResult`, `ScriptedBrowserStudyResult`, `TerminalProductStudyResult`, `ConcurrentSharedWorldStudyResult` | `StudyResult<"computer-use">`, `StudyResult<"scripted">`, `StudyResult<"terminal">`, `StudyResult<"shared-world">` |
|
|
1566
|
+
| `SubjectPhaseEvent` | the `subject-phase` `StudyEvent` through `onEvent`. Its `type` is `"subject-phase"`; the phase that was `type` is `name`, and `target` is `{ kind: "subject" }` or `{ kind: "participant", participant }`. `message`, `at`, `ok` and `durationMs` are unchanged |
|
|
1567
|
+
| `StudyOutcome.backend`, `LabBackend` | `outcome.route` |
|
|
1568
|
+
| `selectLabBackend`, the `routesTo*` predicates, `actorResolvesToTerminal` | `routeOf(config)` |
|
|
1569
|
+
| `resolveStudyDryRun` | `RunStudyOptions.dryRun`; without it, `scenario.mode` decides |
|
|
1570
|
+
| `cuaLaneCount` | the `plan` `StudyEvent`, which lists every participant |
|
|
1571
|
+
| `resolveSeatUrl` | `parseStudy`, which refuses a participant entry that is not same-origin loopback; build the URL with `new URL(entry, serveUrl)` |
|
|
1572
|
+
| `cuaLaneValidationReason`, `sharedWorldValidationReason`, `concurrentSharedWorldValidationReason`, `externalPublicSharedWorldValidationReason` | `parseStudy`, which returns the same reason |
|
|
1573
|
+
| `MAX_CUA_LANES` | none; `parseStudy` refuses a roster of more than 16 participants |
|
|
1497
1574
|
|
|
1498
1575
|
## Product-Adapter Extension Seam
|
|
1499
1576
|
|
|
1500
1577
|
The terminal-product and browser/computer-use routes let an adopter attach
|
|
1501
|
-
product-specific scoring + feedback as a
|
|
1502
|
-
core. The seam is `
|
|
1578
|
+
product-specific scoring + feedback as a thin in-repo extension without forking
|
|
1579
|
+
core. The seam is `RunStudyOptions.scorer`, an `AdapterScorerModule`, for terminal-product,
|
|
1503
1580
|
computer-use and shared-world runs; the CLI loads the same module with `--scorer`. This is never a built-in product scorer (the adopter's scorecard
|
|
1504
1581
|
lives in the adopter's repo).
|
|
1505
1582
|
|
|
@@ -1516,8 +1593,8 @@ status, score, summary, data? }`. Core never reads `data`, where the adopter's
|
|
|
1516
1593
|
feedback-candidate shape; product-specific concepts (public CLI/product command
|
|
1517
1594
|
observed, hosted product success-or-blocker, feedback id/draft, media/job/asset
|
|
1518
1595
|
ids, explicit no-media/no-provider-spend proof, defection/friction risk) are
|
|
1519
|
-
recorded
|
|
1520
|
-
validates the
|
|
1596
|
+
recorded only under `adapter: { namespace, data }`, never as core enums. Core
|
|
1597
|
+
validates the shape (a non-empty `namespace` + a `data` record); the keys inside
|
|
1521
1598
|
`data` are the adapter's.
|
|
1522
1599
|
- **Adapter artifacts** (`humanish.adapter-artifact.v1`,
|
|
1523
1600
|
`RunBundle.adapterArtifacts[]`). A namespaced list of local relative artifact
|
|
@@ -1563,7 +1640,7 @@ Acceptance semantics are route-specific:
|
|
|
1563
1640
|
|
|
1564
1641
|
- Terminal-product runs keep the mission-based `review` verdict unchanged for a
|
|
1565
1642
|
library `scorer`; the adapter score is additive. A config-declared scorer
|
|
1566
|
-
(`--scorer` or the
|
|
1643
|
+
(`--scorer` or the study's `review.scorer.ref`) that returns `status: fail`,
|
|
1567
1644
|
throws, or returns a malformed score turns a pass-like verdict into `fail` and
|
|
1568
1645
|
fails the run result.
|
|
1569
1646
|
- Browser/computer-use runs treat `adapterScore.status: fail` as product-red:
|
|
@@ -1574,18 +1651,19 @@ Acceptance semantics are route-specific:
|
|
|
1574
1651
|
evidence.
|
|
1575
1652
|
|
|
1576
1653
|
The `e2b-terminal` substrate is added to `RunFeedbackCandidate.substrate` so a
|
|
1577
|
-
terminal-agent candidate names
|
|
1578
|
-
the existing `e2b-desktop` substrate. The routes invoke hooks over
|
|
1654
|
+
terminal-agent candidate names the substrate it ran on; browser candidates use
|
|
1655
|
+
the existing `e2b-desktop` substrate. The routes invoke hooks over fully-assembled,
|
|
1579
1656
|
redacted evidence (`TerminalProductScoringContext` or
|
|
1580
|
-
`
|
|
1581
|
-
actor and route metadata; all exported public types
|
|
1582
|
-
|
|
1657
|
+
`BrowserScoringContext`: `bundle`, runtime-only `runDir`, the run identifiers
|
|
1658
|
+
`studyId` and `runId`, actor and route metadata; all exported public types; 0.109.0
|
|
1659
|
+
renamed the context's `labId` to `studyId`), scrub+redact returned
|
|
1660
|
+
payloads, and drop any malformed score, candidate, or artifact reference with a
|
|
1583
1661
|
warning so a bad extension never poisons a verifiable bundle. On the terminal
|
|
1584
|
-
route the context also carries `transcript`: the
|
|
1662
|
+
route the context also carries `transcript`: the full normalized session
|
|
1585
1663
|
transcript, source-scrubbed then shape-redacted and byte-identical to the
|
|
1586
1664
|
persisted `terminal-transcript.txt` (the trace's `transcriptTail` is a ~2KB
|
|
1587
1665
|
projection of it), so an adopter rubric can find command-tier evidence anywhere
|
|
1588
|
-
in the session
|
|
1666
|
+
in the session, including outside the tail window. Default behavior
|
|
1589
1667
|
(no hook) is unchanged. `verifyRun` re-checks the surviving shapes fail-closed,
|
|
1590
1668
|
including existence for referenced adapter artifacts.
|
|
1591
1669
|
|
|
@@ -1671,10 +1749,10 @@ bundlePath: .humanish/runs/synthetic-run-bundle-2026-06-02t10-00-00-000z-proof/r
|
|
|
1671
1749
|
checks:
|
|
1672
1750
|
- name: run.json exists
|
|
1673
1751
|
ok: true
|
|
1674
|
-
message: run.json present
|
|
1752
|
+
message: run.json is present
|
|
1675
1753
|
- name: redaction passed
|
|
1676
1754
|
ok: true
|
|
1677
|
-
message: redaction
|
|
1755
|
+
message: redaction passed
|
|
1678
1756
|
shareSafety:
|
|
1679
1757
|
status: share_ready
|
|
1680
1758
|
reasons: []
|