humanish 0.107.0 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +22 -17
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +51 -44
- package/README.md +145 -172
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +8 -6
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +2 -2
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +16 -16
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/admission-limit.d.ts +1 -1
- package/dist/actors/computer-use/admission-limit.js +1 -1
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +10 -10
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/ending.d.ts +5 -5
- package/dist/actors/computer-use/loop/ending.js +7 -7
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +9 -9
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +1 -1
- package/dist/actors/computer-use/loop/session.js +3 -3
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +9 -8
- package/dist/actors/computer-use/loop/types.d.ts +25 -23
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +11 -8
- package/dist/actors/computer-use/openai-provider.js +45 -34
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/contract.d.ts +78 -43
- package/dist/actors/contract.js +29 -23
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +10 -9
- package/dist/actors/local-agent/cli.d.ts +8 -6
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +6 -6
- package/dist/actors/registry.d.ts +10 -10
- package/dist/actors/registry.js +18 -17
- package/dist/actors/scripted-browser/actor.d.ts +8 -8
- package/dist/actors/scripted-browser/actor.js +16 -16
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/service.js +5 -5
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +54 -33
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/lab-format.d.ts +5 -4
- package/dist/cli/commands/lab-format.js +35 -23
- package/dist/cli/commands/lab-route-computer-use.js +6 -7
- package/dist/cli/commands/lab-route-preview.js +4 -3
- package/dist/cli/commands/lab-route-shared-world.js +3 -3
- package/dist/cli/commands/lab-run.js +10 -11
- package/dist/cli/commands/lab-scorer.d.ts +2 -2
- package/dist/cli/commands/lab-scorer.js +1 -1
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.js +147 -108
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +137 -138
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +26 -21
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +182 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +21 -21
- package/dist/cli/commands/watch.js +60 -75
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +15 -5
- package/dist/cli/doctor.js +103 -48
- package/dist/cli/first-run-path.d.ts +12 -10
- package/dist/cli/first-run-path.js +30 -28
- package/dist/cli/io.d.ts +41 -6
- package/dist/cli/io.js +97 -22
- package/dist/cli/observer-follow.d.ts +2 -2
- package/dist/cli/observer-follow.js +5 -6
- package/dist/cli/orientation.d.ts +6 -3
- package/dist/cli/orientation.js +43 -39
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +109 -40
- package/dist/cli/telemetry.d.ts +15 -15
- package/dist/cli/telemetry.js +48 -40
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.js +2 -2
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +2 -2
- package/dist/comms/fake-inbox.js +2 -2
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +36 -37
- package/dist/comms/sandbox-catch.js +34 -35
- package/dist/comms/setup.js +42 -8
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +36 -78
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +7 -8
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/guest/chromium-text.js +2 -2
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/runtime.js +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +8 -6
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/lab/adapter-extension.d.ts +7 -7
- package/dist/lab/adapter-extension.js +13 -36
- package/dist/lab/adapter-scorer-loader.d.ts +7 -7
- package/dist/lab/adapter-scorer-loader.js +32 -32
- package/dist/lab/composition-rules.js +42 -42
- package/dist/lab/config.js +65 -25
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +8 -8
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +117 -57
- package/dist/lab/doctor.d.ts +10 -3
- package/dist/lab/doctor.js +47 -9
- package/dist/lab/init-templates.js +147 -147
- package/dist/lab/init.d.ts +1 -1
- package/dist/lab/init.js +41 -9
- package/dist/lab/keys.d.ts +2 -0
- package/dist/lab/keys.js +42 -8
- package/dist/lab/lab-deps.d.ts +7 -12
- package/dist/lab/parse/actors.js +9 -9
- package/dist/lab/parse/comms.js +5 -5
- package/dist/lab/parse/execution.js +13 -13
- package/dist/lab/parse/study-v3.d.ts +23 -0
- package/dist/lab/parse/study-v3.js +259 -0
- package/dist/lab/parse/subject-state.d.ts +7 -7
- package/dist/lab/parse/subject-state.js +16 -16
- package/dist/lab/parse/subject.js +28 -28
- package/dist/lab/parse/values.d.ts +1 -1
- package/dist/lab/parse/values.js +3 -3
- package/dist/lab/persona-resolve.d.ts +4 -4
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/plan-participants.d.ts +2 -2
- package/dist/lab/plan-types.d.ts +4 -4
- package/dist/lab/plan.d.ts +1 -7
- package/dist/lab/plan.js +10 -41
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -4
- package/dist/lab/preflight.d.ts +7 -5
- package/dist/lab/preflight.js +5 -5
- package/dist/lab/routing.d.ts +31 -25
- package/dist/lab/routing.js +60 -29
- package/dist/lab/run-lab-events.d.ts +0 -3
- package/dist/lab/run-lab-events.js +0 -6
- package/dist/lab/run-lab-homes.d.ts +22 -10
- package/dist/lab/run-lab-homes.js +5 -1
- package/dist/lab/run-lab-options.d.ts +1 -1
- package/dist/lab/run-lab-options.js +16 -13
- package/dist/lab/summary.d.ts +7 -6
- package/dist/lab/summary.js +10 -10
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +101 -95
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +13 -13
- package/dist/lab/validation.js +44 -42
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +61 -33
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +6 -6
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +1 -1
- package/dist/observer/library.js +4 -2
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +10 -5
- package/dist/observer/run-routes.d.ts +3 -3
- package/dist/observer/run-routes.js +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +15 -15
- package/dist/routes/computer-use/bundle.js +3 -3
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
- package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
- package/dist/routes/computer-use/external-comms.d.ts +1 -1
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +18 -18
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-flush.d.ts +1 -1
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +4 -2
- package/dist/routes/computer-use/live-phase.js +6 -6
- package/dist/routes/computer-use/local-vm.js +1 -1
- package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
- package/dist/routes/computer-use/participant-desktop.js +4 -4
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +9 -9
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +31 -13
- package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
- package/dist/routes/computer-use/participant-prompt.js +6 -6
- package/dist/routes/computer-use/participant-runs.d.ts +7 -7
- package/dist/routes/computer-use/participant-runs.js +13 -13
- package/dist/routes/computer-use/plan.js +22 -22
- package/dist/routes/computer-use/preflight.js +21 -21
- package/dist/routes/computer-use/rerun-selection.js +1 -1
- package/dist/routes/computer-use/result.js +11 -11
- package/dist/routes/computer-use/route.d.ts +2 -1
- package/dist/routes/computer-use/route.js +15 -14
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +31 -31
- package/dist/routes/computer-use/setup.d.ts +1 -1
- package/dist/routes/computer-use/setup.js +17 -18
- package/dist/routes/computer-use/single-bundle.d.ts +7 -7
- package/dist/routes/computer-use/single-bundle.js +28 -30
- package/dist/routes/computer-use/subject-projection.d.ts +1 -1
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +40 -42
- package/dist/routes/computer-use/types.js +10 -10
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -4
- package/dist/routes/scripted/bundle.d.ts +2 -2
- package/dist/routes/scripted/bundle.js +13 -12
- package/dist/routes/scripted/plan.d.ts +1 -1
- package/dist/routes/scripted/plan.js +9 -9
- package/dist/routes/scripted/result.js +5 -5
- package/dist/routes/scripted/route.js +5 -6
- package/dist/routes/scripted/scenario.js +2 -2
- package/dist/routes/scripted/setup.js +7 -7
- package/dist/routes/scripted/subject.js +1 -1
- package/dist/routes/scripted/surface-records.js +3 -3
- package/dist/routes/scripted/types.d.ts +3 -5
- package/dist/routes/scripted/types.js +1 -1
- package/dist/routes/shared-world/bundle-records.js +9 -8
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +40 -38
- package/dist/routes/shared-world/checkpoints.d.ts +1 -1
- package/dist/routes/shared-world/checkpoints.js +1 -1
- package/dist/routes/shared-world/comms.d.ts +5 -5
- package/dist/routes/shared-world/comms.js +14 -14
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +7 -6
- package/dist/routes/shared-world/participant-specs.js +31 -24
- package/dist/routes/shared-world/plan.js +7 -7
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.js +14 -13
- package/dist/routes/shared-world/result.js +20 -21
- package/dist/routes/shared-world/route.js +23 -22
- package/dist/routes/shared-world/setup.d.ts +3 -3
- package/dist/routes/shared-world/setup.js +4 -4
- package/dist/routes/shared-world/types.d.ts +30 -28
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +3 -3
- package/dist/routes/terminal/adapter.js +5 -5
- package/dist/routes/terminal/bundle.d.ts +3 -3
- package/dist/routes/terminal/bundle.js +22 -21
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +7 -7
- package/dist/routes/terminal/dry-run.js +4 -4
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/live-finish.js +3 -3
- package/dist/routes/terminal/live-sandbox.js +12 -13
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.js +11 -11
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.js +8 -8
- package/dist/routes/terminal/route.js +6 -7
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.js +8 -7
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +2 -2
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +26 -28
- package/dist/routes/terminal/types.js +3 -3
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +46 -46
- package/dist/run/bundle.js +2 -1
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.js +7 -1
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +18 -18
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +20 -13
- package/dist/run/projection.d.ts +14 -14
- package/dist/run/projection.js +15 -15
- package/dist/run/reclaim.js +2 -2
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +8 -6
- package/dist/run/run-index.js +15 -16
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +5 -4
- package/dist/run/run.js +1 -1
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +36 -35
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +6 -6
- package/dist/run/stats.d.ts +12 -6
- package/dist/run/stats.js +116 -58
- package/dist/run/status.d.ts +8 -29
- package/dist/run/status.js +5 -27
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +6 -6
- package/dist/run/study-provenance.d.ts +47 -0
- package/dist/run/study-provenance.js +63 -0
- package/dist/run/study-result.d.ts +16 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-lab.d.ts +7 -7
- package/dist/run-lab.js +1 -3
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +43 -0
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/subject/clone.d.ts +1 -1
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.js +1 -1
- package/dist/subject/local-tree.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +8 -9
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +5 -5
- package/dist/subject/steps.js +4 -4
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
- package/dist/substrates/e2b/desktop-browser.js +8 -8
- package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
- package/dist/substrates/e2b/desktop-cdp.js +8 -8
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
- package/dist/substrates/e2b/desktop-executor.js +1 -1
- package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
- package/dist/substrates/e2b/desktop-geometry.js +7 -7
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/sandbox.d.ts +1 -1
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +6 -6
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +16 -16
- package/dist/tui/contract.js +10 -10
- package/dist/tui/launch.d.ts +4 -4
- package/dist/tui/launch.js +18 -19
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +82 -82
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +92 -43
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +56 -87
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +61 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +5 -5
- package/docs/architecture/terminal-product-route.md +67 -107
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +2 -5
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +45 -44
- package/docs/contracts/schemas.md +421 -362
- package/docs/contracts/study-analysis.md +3 -3
- package/docs/contracts/study-costs.md +11 -7
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +60 -58
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- package/docs/roadmap/world-class-open-source-v0.md +0 -311
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Versioned, deliberately narrow profile qualified with an account-backed vision turn.
|
|
2
2
|
* The CLI still advertises code-mode tools: disabling their host is the enforcement
|
|
3
|
-
* boundary. Feature names alone are not proof that a tool has been removed.
|
|
4
|
-
*
|
|
3
|
+
* boundary. Feature names alone are not proof that a tool has been removed. Which CLI
|
|
4
|
+
* releases launch is decided in codex-admission.ts. */
|
|
5
5
|
export const RESTRICTED_CODEX_ANALYSIS_IDENTITY = {
|
|
6
6
|
provider: "codex",
|
|
7
7
|
authMode: "chatgpt",
|
|
@@ -12,8 +12,8 @@ export interface RestrictedCodexSessionOptions {
|
|
|
12
12
|
/** The release a caller already recorded (an analysis identity); any other release is refused. */
|
|
13
13
|
cliVersion?: string;
|
|
14
14
|
/**
|
|
15
|
-
* Bypasses
|
|
16
|
-
*
|
|
15
|
+
* Bypasses launch admission: admits exactly this list. It exists only so
|
|
16
|
+
* scripts/codex-qualify.mjs can launch a candidate admission would refuse. No library export, lab
|
|
17
17
|
* manifest, CLI flag, RunLabOptions field or LabDeps seam reaches it
|
|
18
18
|
* (tests/actors/codex/cli-versions-seam.test.ts).
|
|
19
19
|
*/
|
|
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { chmod, lstat, mkdir, mkdtemp, readdir, realpath, rm, unlink, writeFile, } from "node:fs/promises";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { admitsCodexCliVersion, supportsIsolatedCodex } from "./codex-admission.js";
|
|
6
6
|
import { launchAdmittedAppServer, } from "./restricted-launch.js";
|
|
7
7
|
import { CODEX_IMAGE, CODEX_MAX_OUTPUT_BYTES, CODEX_MAX_REQUEST_BYTES, RESTRICTED_CODEX_ANALYSIS_MODELS, codexRecord, restrictedCodexFailure, restrictedCodexRequestError, } from "./restricted-policy.js";
|
|
8
8
|
import { RestrictedCodexDeadline, RestrictedCodexStop, hasUnclosedChildren, retainUnclosedChild, } from "./restricted-transport.js";
|
|
@@ -312,11 +312,16 @@ function refusedRun(settings, state, request, busy) {
|
|
|
312
312
|
return restrictedCodexFailure("codex_busy");
|
|
313
313
|
const supportedPlatform = operatorAuth
|
|
314
314
|
? restrictedCodexNpmTarget(platform, arch) !== undefined
|
|
315
|
-
: (platform
|
|
315
|
+
: supportsIsolatedCodex(platform, arch);
|
|
316
316
|
if (!supportedPlatform)
|
|
317
317
|
return restrictedCodexFailure("codex_unsupported_platform");
|
|
318
318
|
return undefined;
|
|
319
319
|
}
|
|
320
|
+
/** Which releases a session starts: launch admission, or the qualifier's exact list. */
|
|
321
|
+
function launchAdmission(options) {
|
|
322
|
+
const exact = options.cliVersions;
|
|
323
|
+
return exact === undefined ? admitsCodexCliVersion : (version) => exact.includes(version);
|
|
324
|
+
}
|
|
320
325
|
export function createRestrictedCodexSession(options = {}) {
|
|
321
326
|
// Option reads keep their old order: platform, arch, env, participant, spawnFn, cliVersions.
|
|
322
327
|
const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
|
|
@@ -331,7 +336,7 @@ export function createRestrictedCodexSession(options = {}) {
|
|
|
331
336
|
operatorAuth: participant?.authMode === "operator",
|
|
332
337
|
reasoningEffort: participant?.reasoningEffort ?? "low",
|
|
333
338
|
spawnFn: options.spawnFn ?? ((file, args, spawnOptions) => spawn(file, args, spawnOptions)),
|
|
334
|
-
|
|
339
|
+
admits: launchAdmission(options),
|
|
335
340
|
};
|
|
336
341
|
const state = {
|
|
337
342
|
work: undefined,
|
|
@@ -434,7 +439,7 @@ export async function checkRestrictedCodexSessionReadiness(input = {}, options =
|
|
|
434
439
|
* `--version` runs with a private temporary home, removed afterwards. */
|
|
435
440
|
export async function detectRestrictedCodexCliVersion(input = {}, options = {}) {
|
|
436
441
|
const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
|
|
437
|
-
if (!(
|
|
442
|
+
if (!supportsIsolatedCodex(platform, arch))
|
|
438
443
|
return { cliVersion: null, errorCode: "codex_unsupported_platform" };
|
|
439
444
|
const sourceEnv = options.env ?? process.env;
|
|
440
445
|
const deadline = new RestrictedCodexDeadline(input.timeoutMs ?? 15_000, input.signal);
|
|
@@ -444,7 +449,7 @@ export async function detectRestrictedCodexCliVersion(input = {}, options = {})
|
|
|
444
449
|
work = await realpath(await mkdtemp(path.join(options.tempRoot ?? tmpdir(), "humanish-codex-version-")));
|
|
445
450
|
const home = path.join(work, "home");
|
|
446
451
|
await mkdir(home, { mode: 0o700 });
|
|
447
|
-
const cliVersion = await checkVersion(file, childEnvironment(sourceEnv, home, work), work, options.spawnFn ?? ((command, args, settings) => spawn(command, args, settings)), deadline, options
|
|
452
|
+
const cliVersion = await checkVersion(file, childEnvironment(sourceEnv, home, work), work, options.spawnFn ?? ((command, args, settings) => spawn(command, args, settings)), deadline, launchAdmission(options), options.cliVersion);
|
|
448
453
|
return { cliVersion, errorCode: null };
|
|
449
454
|
}
|
|
450
455
|
catch (error) {
|
|
@@ -10,7 +10,7 @@ export interface CuaActorSessionOptions {
|
|
|
10
10
|
instructions: string;
|
|
11
11
|
/** Provenance of the persona this actor embodies (id + applied traits + prompt digest). */
|
|
12
12
|
persona: ActorPersonaRef;
|
|
13
|
-
/** Hard wall-clock runaway guard
|
|
13
|
+
/** Hard wall-clock runaway guard: the only count-free hard stop the loop honors. */
|
|
14
14
|
timeoutMs: number;
|
|
15
15
|
signal?: AbortSignal;
|
|
16
16
|
/** Live provider construction (used when `provider` is not injected). */
|
|
@@ -19,10 +19,10 @@ export interface CuaActorSessionOptions {
|
|
|
19
19
|
desktop?: E2BDesktopLike;
|
|
20
20
|
executorOptions?: E2BDesktopExecutorOptions;
|
|
21
21
|
/**
|
|
22
|
-
* DI seams
|
|
23
|
-
* callers use them to drive a state-driven, non-vision flow). NOTE: a
|
|
24
|
-
* whose observe() returns no screenshot
|
|
25
|
-
* paired with a
|
|
22
|
+
* DI seams: inject to bypass live construction (CI uses these for zero-spend tests; library
|
|
23
|
+
* callers use them to drive a state-driven, non-vision flow). NOTE: a state executor (one
|
|
24
|
+
* whose observe() returns no screenshot; see CuaObservation.screenshot optional) must be
|
|
25
|
+
* paired with a non-vision provider (requiresFrame falsey). The default OpenAI provider is
|
|
26
26
|
* vision-based and would fail closed against a screenshot-less observation. See
|
|
27
27
|
* docs/architecture/state-driven-executor.md.
|
|
28
28
|
*/
|
|
@@ -39,7 +39,7 @@ export interface CuaActorSessionOptions {
|
|
|
39
39
|
idleSteps?: number;
|
|
40
40
|
noProgressSteps?: number;
|
|
41
41
|
/**
|
|
42
|
-
* Redact persisted screenshots (blur+downscale). Default
|
|
42
|
+
* Redact persisted screenshots (blur+downscale). Default `false`: full fidelity for local use.
|
|
43
43
|
* Set true for unowned subjects or share-as-is bundles. The provider always sees raw frames.
|
|
44
44
|
*/
|
|
45
45
|
redactScreenshots?: boolean;
|
|
@@ -49,29 +49,29 @@ export interface CuaActorSessionOptions {
|
|
|
49
49
|
writeScreenshot?: (name: string, bytes: Buffer) => Promise<string>;
|
|
50
50
|
/** Deterministic harness-owned stop guards evaluated between model turns. */
|
|
51
51
|
stopWhen?: StopWhen;
|
|
52
|
-
/** A declared observation window
|
|
52
|
+
/** A declared observation window, forwarded to the loop. */
|
|
53
53
|
dwell?: DwellWindow;
|
|
54
|
-
/** The lab's declared protocol; the loop records a corroborated task funnel on the trace
|
|
55
|
-
* Only the `success` criteria are read here
|
|
54
|
+
/** The lab's declared protocol; the loop records a corroborated task funnel on the trace.
|
|
55
|
+
* Only the `success` criteria are read here; the participant-facing goals are already composed
|
|
56
56
|
* into `instructions` upstream, and the criteria never reach the prompt. */
|
|
57
57
|
tasks?: readonly LabTask[];
|
|
58
|
-
/**
|
|
58
|
+
/** Fail-closed spend cap (USD) threaded to the loop; absent = uncapped. See CuaLoopOptions.maxUsd. */
|
|
59
59
|
maxUsd?: number;
|
|
60
60
|
/** Injected pure per-turn cost estimator paired with `maxUsd`. See CuaLoopOptions.estimateTurnCostUsd. */
|
|
61
61
|
estimateTurnCostUsd?: (usage: ActorTokenUsage) => number | null;
|
|
62
|
-
/**
|
|
62
|
+
/** Run-level spend guard threaded to the loop. See CuaLoopOptions.overRunBudget. */
|
|
63
63
|
overRunBudget?: (usage: ActorTokenUsage) => string | null;
|
|
64
64
|
/** Stricter unknown-usage policy for capped sessions (see CuaLoopOptions); it also makes the
|
|
65
65
|
* OpenAI provider send one HTTP dispatch per turn. Library-only. */
|
|
66
66
|
requireReportedUsageForSpendCap?: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* the concurrent shared-world handoff barrier to latch a host
|
|
67
|
+
/** Runtime-only observed-URL callback threaded to the loop; see CuaLoopOptions.onObservedUrl. Used by
|
|
68
|
+
* the concurrent shared-world handoff barrier to latch a host's live /lobby/CODE URL. */
|
|
69
69
|
onObservedUrl?: (url: string | undefined) => void;
|
|
70
|
-
/**
|
|
70
|
+
/** Runtime-only per-turn narration callback threaded to the loop; see CuaLoopOptions.onMessage. */
|
|
71
71
|
onMessage?: (text: string) => void;
|
|
72
|
-
/**
|
|
72
|
+
/** Runtime-only per-turn raw-frame callback threaded to the loop; see CuaLoopOptions.onScreenshot. */
|
|
73
73
|
onScreenshot?: (frame: Buffer) => void;
|
|
74
|
-
/** Per-turn trace snapshot callback threaded to the loop
|
|
74
|
+
/** Per-turn trace snapshot callback threaded to the loop; see CuaLoopOptions.onTrace. */
|
|
75
75
|
onTrace?: (items: readonly ActorTraceItem[], usage: ActorTokenUsage, metadata?: CuaLiveMetadata) => void;
|
|
76
76
|
}
|
|
77
77
|
export declare function runCuaActorSession(options: CuaActorSessionOptions): Promise<CuaLoopResult>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// The registry-facing wrapper for the OpenAI Computer Use (CUA) actor. runComputerUseLoop needs
|
|
2
2
|
// fully-constructed provider/executor instances; exposing that raw through the actor registry
|
|
3
3
|
// would leak adapter construction to every call site. So runCuaActorSession takes intent-level
|
|
4
|
-
// fields and constructs the provider/executor internally
|
|
4
|
+
// fields and constructs the provider/executor internally, with DI seams (provider/executor/now)
|
|
5
5
|
// so CI can drive the real loop with fakes and zero network/zero spend (mirrors how the Claude
|
|
6
6
|
// adapter injects its queryFn).
|
|
7
7
|
//
|
|
8
8
|
// The loop already returns a fully-formed ActorTrace at result.trace, so there is no separate
|
|
9
|
-
// toActorTrace mapper
|
|
9
|
+
// toActorTrace mapper: runCuaActorSession returns the CuaLoopResult unchanged.
|
|
10
10
|
import { runComputerUseLoop, } from "./loop.js";
|
|
11
11
|
import { createE2BDesktopExecutor, } from "../../substrates/e2b/desktop-executor.js";
|
|
12
12
|
import { createOpenAiResponsesProvider, } from "./openai-provider.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A caller's adapter refused this request
|
|
2
|
+
* A caller's adapter refused this request before provider dispatch because a configured
|
|
3
3
|
* local control limit was reached. This is an adapter declaration, not a provider response
|
|
4
4
|
* or independent transport/billing attestation. Never use it for a dispatched request whose
|
|
5
5
|
* outcome or usage is unknown. Import this class from the same humanish installation as the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const admissionLimits = new WeakSet();
|
|
2
2
|
/**
|
|
3
|
-
* A caller's adapter refused this request
|
|
3
|
+
* A caller's adapter refused this request before provider dispatch because a configured
|
|
4
4
|
* local control limit was reached. This is an adapter declaration, not a provider response
|
|
5
5
|
* or independent transport/billing attestation. Never use it for a dispatched request whose
|
|
6
6
|
* outcome or usage is unknown. Import this class from the same humanish installation as the
|
|
@@ -3,10 +3,10 @@ import type { CuaAction, CuaTurnRequest } from "./types.js";
|
|
|
3
3
|
/** A public-safe one-line action label. Never includes raw typed text. */
|
|
4
4
|
export declare function describeCuaAction(action: CuaAction): string;
|
|
5
5
|
/**
|
|
6
|
-
* A public-safe fingerprint of
|
|
7
|
-
* thing again" from "trying something new"
|
|
6
|
+
* A public-safe fingerprint of one turn's actions, used only in memory to tell "trying the same
|
|
7
|
+
* thing again" from "trying something new".
|
|
8
8
|
*
|
|
9
|
-
* Never includes typed text or key contents
|
|
9
|
+
* Never includes typed text or key contents: a `type` contributes its length, exactly as
|
|
10
10
|
* describeCuaAction does, so this can never become a keylogger. Coordinates are bucketed so that
|
|
11
11
|
* re-clicking the same control counts as a repeat while moving to a different control does not.
|
|
12
12
|
*/
|
|
@@ -47,10 +47,10 @@ function describeAction(action) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* A public-safe fingerprint of
|
|
51
|
-
* thing again" from "trying something new"
|
|
50
|
+
* A public-safe fingerprint of one turn's actions, used only in memory to tell "trying the same
|
|
51
|
+
* thing again" from "trying something new".
|
|
52
52
|
*
|
|
53
|
-
* Never includes typed text or key contents
|
|
53
|
+
* Never includes typed text or key contents: a `type` contributes its length, exactly as
|
|
54
54
|
* describeCuaAction does, so this can never become a keylogger. Coordinates are bucketed so that
|
|
55
55
|
* re-clicking the same control counts as a repeat while moving to a different control does not.
|
|
56
56
|
*/
|
|
@@ -121,8 +121,8 @@ export async function runActionBatch(session, actions) {
|
|
|
121
121
|
if (actionHistory.recentActionTitles.length > RECENT_ACTION_TITLES)
|
|
122
122
|
actionHistory.recentActionTitles.shift();
|
|
123
123
|
trace.bump("actions");
|
|
124
|
-
// Classify
|
|
125
|
-
//
|
|
124
|
+
// Classify before execute, mirroring counts.actions: the record is of what the actor
|
|
125
|
+
// chose, so an action that then fails to actuate is still a record of the route
|
|
126
126
|
// it reached for.
|
|
127
127
|
actionHistory.affordances.push(classifyCuaAction(action));
|
|
128
128
|
session.phase = `executing ${title}`;
|
|
@@ -153,7 +153,7 @@ export async function runActionBatch(session, actions) {
|
|
|
153
153
|
if (isCuaExecutorError(error) || !isCommandExitError(error))
|
|
154
154
|
throw error;
|
|
155
155
|
// A skipped action changes nothing on screen, so a persistently-failing run makes no
|
|
156
|
-
// progress and still terminates
|
|
156
|
+
// progress and still terminates via the idle/no-progress backstop (gave_up),
|
|
157
157
|
// never a silent actor_error and never an infinite loop.
|
|
158
158
|
recordCommandFailure(session, title, error);
|
|
159
159
|
continue;
|
|
@@ -164,8 +164,8 @@ export async function runActionBatch(session, actions) {
|
|
|
164
164
|
lifecycle: "completed",
|
|
165
165
|
title,
|
|
166
166
|
...(action.kind === "speak" ? { text: session.redactNarration(action.text) } : {}),
|
|
167
|
-
// Structured pin coordinates
|
|
168
|
-
// pins render
|
|
167
|
+
// Structured pin coordinates, exactly the click classes the Observer
|
|
168
|
+
// pins render: recorded fact instead of a title re-parse downstream.
|
|
169
169
|
...(action.kind === "click" || action.kind === "double_click"
|
|
170
170
|
? { coord: { x: action.x, y: action.y } }
|
|
171
171
|
: {}),
|
|
@@ -180,9 +180,9 @@ function countAttempt(session, action, title, status) {
|
|
|
180
180
|
session.trace.counts.materialActions += 1;
|
|
181
181
|
}
|
|
182
182
|
/**
|
|
183
|
-
* Execute one action. Idle actions only look
|
|
183
|
+
* Execute one action. Idle actions only look: a `wait` that hangs inside the SDK has in
|
|
184
184
|
* effect waited, so a stalled one is skipped with a notice and loses nothing the participant
|
|
185
|
-
* chose. An action is recorded as completed only after execute() resolves
|
|
185
|
+
* chose. An action is recorded as completed only after execute() resolves.
|
|
186
186
|
*/
|
|
187
187
|
async function dispatchAction(session, action, title) {
|
|
188
188
|
if (!isIdleAction(action)) {
|
|
@@ -2,10 +2,10 @@ import type { CuaAction, CuaObservation } from "./types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* A deterministic, bounded, sorted-key projection of an appState object, used as the friction
|
|
4
4
|
* loop's progress key. Two structurally-equal states (regardless of key insertion order) map
|
|
5
|
-
* to the
|
|
5
|
+
* to the same string, so key reordering can never fabricate a progress delta; two different
|
|
6
6
|
* states map to different strings (within the caps).
|
|
7
7
|
*
|
|
8
|
-
* Correctness
|
|
8
|
+
* Correctness depends on this: it must not throw on a cyclic or huge input. Cycles are detected
|
|
9
9
|
* with a seen-set (a back-edge degrades to the marker "[Circular]"); depth, key count, array
|
|
10
10
|
* length, string length, and total output length are all capped so an adversarial or merely
|
|
11
11
|
* large appState degrades to a bounded value rather than crashing the loop. Pure: it never
|
|
@@ -14,7 +14,7 @@ import type { CuaAction, CuaObservation } from "./types.js";
|
|
|
14
14
|
export declare function stableProgressKey(appState: Record<string, unknown>): string;
|
|
15
15
|
export interface Backstop {
|
|
16
16
|
readonly progressKey: string;
|
|
17
|
-
/** The last few turns' action fingerprints, in memory only, for the
|
|
17
|
+
/** The last few turns' action fingerprints, in memory only, for the corroboration rule below. */
|
|
18
18
|
readonly recentFingerprints: readonly string[];
|
|
19
19
|
readonly consecutiveIdle: number;
|
|
20
20
|
readonly consecutiveNoProgress: number;
|
|
@@ -4,9 +4,9 @@ import { actionFingerprint, isIdleTurn } from "./actions.js";
|
|
|
4
4
|
// streak (turns that neither change the UI state nor try something new). It is a pure fold over
|
|
5
5
|
// turns, never a turn budget.
|
|
6
6
|
const IDLE_PROGRESS_FORGIVENESS_STEPS = 2;
|
|
7
|
-
/** How many recent turns the repetition check looks back over
|
|
7
|
+
/** How many recent turns the repetition check looks back over. */
|
|
8
8
|
const ACTION_REPEAT_WINDOW = 3;
|
|
9
|
-
/** Pixels of vertical scroll per progress bucket
|
|
9
|
+
/** Pixels of vertical scroll per progress bucket: a real scroll step (typically >=100px)
|
|
10
10
|
* crosses a bucket and counts as progress; sub-bucket jiggle does not, so an actor nudging the
|
|
11
11
|
* same dead panel cannot stay "progressing" forever. */
|
|
12
12
|
const SCROLL_PROGRESS_BUCKET_PX = 200;
|
|
@@ -22,10 +22,10 @@ const STABLE_KEY_MAX_TOTAL = 8192;
|
|
|
22
22
|
/**
|
|
23
23
|
* A deterministic, bounded, sorted-key projection of an appState object, used as the friction
|
|
24
24
|
* loop's progress key. Two structurally-equal states (regardless of key insertion order) map
|
|
25
|
-
* to the
|
|
25
|
+
* to the same string, so key reordering can never fabricate a progress delta; two different
|
|
26
26
|
* states map to different strings (within the caps).
|
|
27
27
|
*
|
|
28
|
-
* Correctness
|
|
28
|
+
* Correctness depends on this: it must not throw on a cyclic or huge input. Cycles are detected
|
|
29
29
|
* with a seen-set (a back-edge degrades to the marker "[Circular]"); depth, key count, array
|
|
30
30
|
* length, string length, and total output length are all capped so an adversarial or merely
|
|
31
31
|
* large appState degrades to a bounded value rather than crashing the loop. Pure: it never
|
|
@@ -107,8 +107,8 @@ function progressKeyOf(observation) {
|
|
|
107
107
|
const base = observation.appState !== undefined
|
|
108
108
|
? stableProgressKey(observation.appState)
|
|
109
109
|
: observation.stateSignature;
|
|
110
|
-
// Scroll position is state
|
|
111
|
-
// the participant genuinely advances, so the offset rides the key
|
|
110
|
+
// Scroll position is state: a scroll-pinned section keeps the frame hash constant while
|
|
111
|
+
// the participant genuinely advances, so the offset rides the key, bucketed, never raw.
|
|
112
112
|
return observation.scrollY === undefined
|
|
113
113
|
? base
|
|
114
114
|
: `${base}#s${Math.round(observation.scrollY / SCROLL_PROGRESS_BUCKET_PX)}`;
|
|
@@ -127,23 +127,23 @@ export function advanceBackstop(previous, turn, limits) {
|
|
|
127
127
|
const idle = isIdleTurn(turn.actions);
|
|
128
128
|
const progressKey = progressKeyOf(turn.observation);
|
|
129
129
|
const frameChanged = progressKey !== previous.progressKey;
|
|
130
|
-
//
|
|
130
|
+
// Corroboration. A stale frame alone is not evidence of a stuck agent. The frame hash is
|
|
131
131
|
// a coarse whole-screen measure, and on a light-themed web app it can miss a renamed row, a new
|
|
132
|
-
// list item, or an opened panel
|
|
132
|
+
// list item, or an opened panel: a measured run had 9 visibly different consecutive frames hash
|
|
133
133
|
// identically while the agent was a foreign key away from finishing. Ending a participant on that
|
|
134
134
|
// signal alone recorded working sessions as `gave_up`, capping every browser run at roughly
|
|
135
135
|
// noProgressSteps turns and writing harness artifacts into evidence as actor behavior.
|
|
136
136
|
//
|
|
137
|
-
// So a no-progress turn now requires
|
|
137
|
+
// So a no-progress turn now requires both a stale frame and the agent repeating something it
|
|
138
138
|
// just tried. An agent doing varied work is never counted stuck, however blind the hash is;
|
|
139
|
-
// an agent re-clicking the same dead control trips it as fast as it did before
|
|
139
|
+
// an agent re-clicking the same dead control trips it as fast as it did before, arguably
|
|
140
140
|
// faster, since that is the actual signature of being stuck.
|
|
141
141
|
const fingerprint = actionFingerprint(turn.actions);
|
|
142
142
|
const repeatingRecentAction = fingerprint.length > 0 && previous.recentFingerprints.includes(fingerprint);
|
|
143
143
|
const recentFingerprints = [...previous.recentFingerprints, fingerprint].slice(-ACTION_REPEAT_WINDOW);
|
|
144
|
-
// Corroboration governs the
|
|
144
|
+
// Corroboration governs the frame-staleness backstop only. The idle backstop below is a direct
|
|
145
145
|
// behavioral signal already (the agent took nothing but screenshots and waits), so it keeps
|
|
146
|
-
// reading the frame on its own
|
|
146
|
+
// reading the frame on its own: a repeated screenshot is exactly what an idle streak is, and
|
|
147
147
|
// feeding repetition into it would grant an extra forgiveness step for being idle.
|
|
148
148
|
const observedProgress = frameChanged || turn.heardNewSpeech;
|
|
149
149
|
const progressed = observedProgress || !repeatingRecentAction;
|
|
@@ -172,11 +172,13 @@ export function advanceBackstop(previous, turn, limits) {
|
|
|
172
172
|
const hints = [];
|
|
173
173
|
if (consecutiveNoProgress >= noProgressRecoverySteps &&
|
|
174
174
|
consecutiveNoProgress < limits.noProgressSteps) {
|
|
175
|
+
// prose-check: model prompt (the participant model reads this hint, not a person)
|
|
175
176
|
hints.push(`No visible progress for ${consecutiveNoProgress} step(s). ` +
|
|
176
177
|
"If your task calls for waiting for another participant or a pending transition, you may continue waiting. " +
|
|
177
178
|
"Choose whether to continue or stop based on your situation and what you observe.");
|
|
178
179
|
}
|
|
179
180
|
if (consecutiveIdle >= idleRecoverySteps && consecutiveIdle < limits.idleSteps) {
|
|
181
|
+
// prose-check: model prompt (the participant model reads this hint, not a person)
|
|
180
182
|
hints.push(`You are only waiting or taking screenshots for ${consecutiveIdle} step(s). ` +
|
|
181
183
|
"If your task calls for waiting, you may continue within the remaining session time. " +
|
|
182
184
|
"When the relevant controls become actionable, continue your task; describe any blocker you actually encounter.");
|
|
@@ -18,12 +18,12 @@ export interface Stop {
|
|
|
18
18
|
readonly debriefTrigger?: DebriefTrigger;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Read the fixed closing line the prompt asks for
|
|
21
|
+
* Read the fixed closing line the prompt asks for: the first non-empty line of the
|
|
22
22
|
* participant's last message, exactly one of three phrases, punctuation and case forgiven. Anything
|
|
23
23
|
* else is absence, never a guess. Exported for tests.
|
|
24
24
|
*/
|
|
25
25
|
export declare function declaredOutcomeFromClosingLine(message: string | undefined): ParticipantDeclaredOutcome | undefined;
|
|
26
|
-
/** The participant's own word for how it ended: a schema field first, then the closing line
|
|
26
|
+
/** The participant's own word for how it ended: a schema field first, then the closing line. */
|
|
27
27
|
export declare function declaredOutcomeOf(turn: CuaTurn): ParticipantDeclaredOutcome | undefined;
|
|
28
28
|
/**
|
|
29
29
|
* The participant reported a natural endpoint. "not_reached" is a participant who stopped without
|
|
@@ -35,8 +35,8 @@ export declare function participantEnded(turn: CuaTurn, declaredOutcome: Partici
|
|
|
35
35
|
export declare const harnessAborted: Stop;
|
|
36
36
|
/**
|
|
37
37
|
* The wall-clock deadline. A session that took at least one material (non-idle) action before the
|
|
38
|
-
* cap reached its
|
|
39
|
-
*
|
|
38
|
+
* cap reached its budget rather than stalling; a deadline hit with zero material actions is still
|
|
39
|
+
* recorded as a failure (timed_out).
|
|
40
40
|
*/
|
|
41
41
|
export declare function timeLimit(session: LoopSession): Stop;
|
|
42
42
|
/**
|
|
@@ -67,7 +67,7 @@ export declare function providerStalledTwice(turnNumber: number, afterMs: number
|
|
|
67
67
|
export declare function providerInterrupted(interruption: NonNullable<CuaTurn["interruption"]>): Stop;
|
|
68
68
|
/**
|
|
69
69
|
* Safety-check categories are provider-defined enums (e.g. "malicious_instructions"), not free
|
|
70
|
-
* text; the evidence records them (redacted for defense-in-depth) so it shows
|
|
70
|
+
* text; the evidence records them (redacted for defense-in-depth) so it shows why the run paused.
|
|
71
71
|
*/
|
|
72
72
|
export declare function blockedOnSafetyChecks(checks: string): Stop;
|
|
73
73
|
/**
|
|
@@ -3,7 +3,7 @@ import { isCuaPromptRefusedError, isCuaProviderError } from "../provider-error.j
|
|
|
3
3
|
import { CuaAbortError, CuaDeadlineError } from "./race.js";
|
|
4
4
|
import { notice } from "./trace.js";
|
|
5
5
|
/**
|
|
6
|
-
* Read the fixed closing line the prompt asks for
|
|
6
|
+
* Read the fixed closing line the prompt asks for: the first non-empty line of the
|
|
7
7
|
* participant's last message, exactly one of three phrases, punctuation and case forgiven. Anything
|
|
8
8
|
* else is absence, never a guess. Exported for tests.
|
|
9
9
|
*/
|
|
@@ -25,7 +25,7 @@ export function declaredOutcomeFromClosingLine(message) {
|
|
|
25
25
|
return "blocked";
|
|
26
26
|
return undefined;
|
|
27
27
|
}
|
|
28
|
-
/** The participant's own word for how it ended: a schema field first, then the closing line
|
|
28
|
+
/** The participant's own word for how it ended: a schema field first, then the closing line. */
|
|
29
29
|
export function declaredOutcomeOf(turn) {
|
|
30
30
|
return turn.outcome ?? declaredOutcomeFromClosingLine(turn.message);
|
|
31
31
|
}
|
|
@@ -51,8 +51,8 @@ export const harnessAborted = {
|
|
|
51
51
|
};
|
|
52
52
|
/**
|
|
53
53
|
* The wall-clock deadline. A session that took at least one material (non-idle) action before the
|
|
54
|
-
* cap reached its
|
|
55
|
-
*
|
|
54
|
+
* cap reached its budget rather than stalling; a deadline hit with zero material actions is still
|
|
55
|
+
* recorded as a failure (timed_out).
|
|
56
56
|
*/
|
|
57
57
|
export function timeLimit(session) {
|
|
58
58
|
const { timeoutMs } = session;
|
|
@@ -86,8 +86,8 @@ export function spendLimit(session, estimate, maxUsd) {
|
|
|
86
86
|
return {
|
|
87
87
|
completionReason: "budget_reached",
|
|
88
88
|
reason: materialActions > 0
|
|
89
|
-
?
|
|
90
|
-
:
|
|
89
|
+
? `Stopped before the next model turn: ${spend} passed execution.caps.maxUsd=$${maxUsd} after productive activity (${materialActions} material action(s), ${turns} turn(s))`
|
|
90
|
+
: `Stopped before the next model turn: ${spend} passed execution.caps.maxUsd=$${maxUsd} with no material progress`,
|
|
91
91
|
stopCause: "spend_limit",
|
|
92
92
|
};
|
|
93
93
|
}
|
|
@@ -178,7 +178,7 @@ export function providerInterrupted(interruption) {
|
|
|
178
178
|
}
|
|
179
179
|
/**
|
|
180
180
|
* Safety-check categories are provider-defined enums (e.g. "malicious_instructions"), not free
|
|
181
|
-
* text; the evidence records them (redacted for defense-in-depth) so it shows
|
|
181
|
+
* text; the evidence records them (redacted for defense-in-depth) so it shows why the run paused.
|
|
182
182
|
*/
|
|
183
183
|
export function blockedOnSafetyChecks(checks) {
|
|
184
184
|
return {
|
|
@@ -23,8 +23,8 @@ export declare class DesktopObserver {
|
|
|
23
23
|
checkpoint(turnNumber: number): Promise<Checkpoint>;
|
|
24
24
|
/**
|
|
25
25
|
* Hand an observation the next turn may react to to the runtime hooks, and note whether it
|
|
26
|
-
* carried app state. Runtime-only: the
|
|
27
|
-
* and is never persisted.
|
|
26
|
+
* carried app state. Runtime-only: the participant's live location.href goes back to the
|
|
27
|
+
* orchestrator and is never persisted.
|
|
28
28
|
*/
|
|
29
29
|
private handToHooks;
|
|
30
30
|
/**
|
|
@@ -4,7 +4,7 @@ import { CUA_SPEECH_LIMITS } from "../speech.js";
|
|
|
4
4
|
import { dwellCompleted, missingFrame, stopWhenMatched } from "./ending.js";
|
|
5
5
|
import { CuaAbortError, CuaStallError, raceCallBound } from "./race.js";
|
|
6
6
|
import { notice } from "./trace.js";
|
|
7
|
-
// One projection feeds
|
|
7
|
+
// One projection feeds both the stop guard and the task tracker, so a criterion that would stop
|
|
8
8
|
// the run and a criterion that completes a task can never see different evidence for one turn.
|
|
9
9
|
function stopObservationOf(observation) {
|
|
10
10
|
return {
|
|
@@ -72,8 +72,8 @@ export class DesktopObserver {
|
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Hand an observation the next turn may react to to the runtime hooks, and note whether it
|
|
75
|
-
* carried app state. Runtime-only: the
|
|
76
|
-
* and is never persisted.
|
|
75
|
+
* carried app state. Runtime-only: the participant's live location.href goes back to the
|
|
76
|
+
* orchestrator and is never persisted.
|
|
77
77
|
*/
|
|
78
78
|
handToHooks(observation) {
|
|
79
79
|
const { onObservedUrl, onScreenshot } = this.session.settings;
|
|
@@ -118,7 +118,7 @@ export class DesktopObserver {
|
|
|
118
118
|
throw error;
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
// An executor without stallRecovery "fail_closed" gets one retry of a stalled observe
|
|
121
|
+
// An executor without stallRecovery "fail_closed" gets one retry of a stalled observe.
|
|
122
122
|
// One that cannot safely replay a pending request opts out, so even a shorter outer bound stops
|
|
123
123
|
// without retrying.
|
|
124
124
|
async observeBounded(label) {
|
|
@@ -185,19 +185,19 @@ export class DesktopObserver {
|
|
|
185
185
|
}));
|
|
186
186
|
session.trace.bump("screenshots");
|
|
187
187
|
}
|
|
188
|
-
// Evaluated
|
|
188
|
+
// Evaluated before the stopWhen check each turn so a final task whose criterion coincides with
|
|
189
189
|
// the stop condition still lands in the funnel of the very turn that ends the session.
|
|
190
190
|
observeTasks(observation, turnNumber) {
|
|
191
191
|
const { taskTracker } = this.session;
|
|
192
192
|
if (taskTracker === undefined)
|
|
193
193
|
return;
|
|
194
194
|
for (const completion of taskTracker.observe(stopObservationOf(observation), turnNumber)) {
|
|
195
|
-
// The id is researcher-authored config and the kinds are rule-type names; the matched
|
|
196
|
-
// (a URL, page text) never appear here
|
|
195
|
+
// The id is researcher-authored config and the kinds are rule-type names; the matched values
|
|
196
|
+
// (a URL, page text) never appear here: the same discipline as the stopWhen notice.
|
|
197
197
|
this.session.trace.record("notice", () => notice("matched", `task completed: ${this.session.redactNarration(completion.id)}`, this.session.redactNarration(`turn ${turnNumber}; matched rule ${completion.matchedRuleIndex} (${completion.matchedKinds.join("+")})`)));
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
|
-
// The declared observation window
|
|
200
|
+
// The declared observation window. The harness holds, looks, and takes nothing back to
|
|
201
201
|
// the model: no action, no turn, no tokens. It runs once, cut to whatever session budget is
|
|
202
202
|
// left, and says in the trace that the time was deliberate.
|
|
203
203
|
async dwellIfDue(observation, turnNumber) {
|
|
@@ -238,7 +238,7 @@ export class DesktopObserver {
|
|
|
238
238
|
}
|
|
239
239
|
const heldMs = session.now() - dwellStartedAtMs;
|
|
240
240
|
session.trace.record("notice", () => notice(
|
|
241
|
-
// A window that
|
|
241
|
+
// A window that ends the session is structured, harness-owned completion evidence, the
|
|
242
242
|
// same class as a matched stopWhen, and the verdict resolver reads it that way.
|
|
243
243
|
dwell.then === "stop" ? "matched" : "ok", "dwell window complete", `${frames} frame(s) over ${heldMs}ms; no model turn was requested during the window`));
|
|
244
244
|
return { next: dwell.then, heldMs };
|
|
@@ -8,7 +8,7 @@ export type TurnReply = {
|
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
10
|
* Ask the provider for one turn. A fail_closed provider gets one single dispatch; any other is
|
|
11
|
-
* raced against turnTimeoutMs
|
|
11
|
+
* raced against turnTimeoutMs and retried once when it stalls.
|
|
12
12
|
*/
|
|
13
13
|
export declare function requestTurn(session: LoopSession, request: CuaTurnRequest, turnNumber: number): Promise<TurnReply>;
|
|
14
14
|
/**
|
|
@@ -12,7 +12,7 @@ import { reportedCounts, settledReceipt } from "./usage.js";
|
|
|
12
12
|
const CUA_PROVIDER_CLEANUP_GRACE_MS = 5000;
|
|
13
13
|
/**
|
|
14
14
|
* Ask the provider for one turn. A fail_closed provider gets one single dispatch; any other is
|
|
15
|
-
* raced against turnTimeoutMs
|
|
15
|
+
* raced against turnTimeoutMs and retried once when it stalls.
|
|
16
16
|
*/
|
|
17
17
|
export async function requestTurn(session, request, turnNumber) {
|
|
18
18
|
const { provider } = session;
|
|
@@ -7,7 +7,7 @@ import { UsageLedger } from "./usage.js";
|
|
|
7
7
|
// (screenshot, wait, screenshot, wait), and a short idle limit ends that session as gave_up before
|
|
8
8
|
// the mail can arrive.
|
|
9
9
|
const DEFAULT_IDLE_STEPS = 24;
|
|
10
|
-
// A no-progress turn also needs a repeated action
|
|
10
|
+
// A no-progress turn also needs a repeated action, so this needs less headroom than the
|
|
11
11
|
// idle limit.
|
|
12
12
|
const DEFAULT_NO_PROGRESS_STEPS = 20;
|
|
13
13
|
const DEFAULT_TURN_TIMEOUT_MS = 180_000;
|
|
@@ -105,9 +105,9 @@ export class LoopSession {
|
|
|
105
105
|
remaining() {
|
|
106
106
|
return this.timeoutMs - (this.now() - this.startedAtMs);
|
|
107
107
|
}
|
|
108
|
-
// Model-authored narration: literal-scrub known provisioned values,
|
|
108
|
+
// Model-authored narration: literal-scrub known provisioned values, then pattern-redact.
|
|
109
109
|
// A value the model transcribes (a DB password it read on screen) has no shape, so redactText
|
|
110
|
-
// alone cannot catch it
|
|
110
|
+
// alone cannot catch it; the lab's scrubKnownValues, injected as scrubText, closes that.
|
|
111
111
|
redactNarration(text) {
|
|
112
112
|
return this.settings.redaction.redactText(this.scrubText(text));
|
|
113
113
|
}
|
|
@@ -9,7 +9,7 @@ export declare class LostRequestRefused extends Error {
|
|
|
9
9
|
/**
|
|
10
10
|
* The spend caps, checked before the next provider request so a model stuck retrying cannot keep
|
|
11
11
|
* spending. The per-participant cap stops the session once the running estimate crosses maxUsd; a null
|
|
12
|
-
* estimate cannot trip it, because preflight guaranteed a rate. The study budget
|
|
12
|
+
* estimate cannot trip it, because preflight guaranteed a rate. The study budget is checked
|
|
13
13
|
* next.
|
|
14
14
|
*/
|
|
15
15
|
export declare function spendStop(session: LoopSession): Stop | undefined;
|
|
@@ -14,7 +14,7 @@ export class LostRequestRefused extends Error {
|
|
|
14
14
|
/**
|
|
15
15
|
* The spend caps, checked before the next provider request so a model stuck retrying cannot keep
|
|
16
16
|
* spending. The per-participant cap stops the session once the running estimate crosses maxUsd; a null
|
|
17
|
-
* estimate cannot trip it, because preflight guaranteed a rate. The study budget
|
|
17
|
+
* estimate cannot trip it, because preflight guaranteed a rate. The study budget is checked
|
|
18
18
|
* next.
|
|
19
19
|
*/
|
|
20
20
|
export function spendStop(session) {
|