humanish 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +24 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -6
- package/README.md +8 -3
- package/dist/actors/codex/app-server-client.js +2 -1
- package/dist/actors/codex/app-server-trace.d.ts +0 -1
- package/dist/actors/codex/app-server-trace.js +1 -3
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/protocol-compat.d.ts +27 -0
- package/dist/actors/codex/protocol-compat.js +357 -0
- package/dist/actors/codex/protocol-contract.d.ts +61 -0
- package/dist/actors/codex/protocol-contract.js +471 -0
- package/dist/actors/codex/qualified-versions.d.ts +31 -4
- package/dist/actors/codex/qualified-versions.js +51 -6
- package/dist/actors/codex/restricted-executable.d.ts +24 -0
- package/dist/actors/codex/restricted-executable.js +97 -22
- package/dist/actors/codex/restricted-launch.d.ts +7 -1
- package/dist/actors/codex/restricted-launch.js +42 -3
- package/dist/actors/codex/restricted-notifications.d.ts +101 -0
- package/dist/actors/codex/restricted-notifications.js +277 -0
- package/dist/actors/codex/restricted-participant.d.ts +30 -0
- package/dist/actors/codex/restricted-participant.js +60 -2
- package/dist/actors/codex/restricted-policy.d.ts +9 -1
- package/dist/actors/codex/restricted-session.d.ts +14 -1
- package/dist/actors/codex/restricted-session.js +50 -17
- package/dist/actors/codex/restricted-transport.d.ts +29 -0
- package/dist/actors/codex/restricted-transport.js +139 -27
- package/dist/actors/codex/restricted-turn.d.ts +19 -4
- package/dist/actors/codex/restricted-turn.js +43 -30
- package/dist/actors/computer-use/actor.d.ts +1 -1
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/loop/backstop.js +1 -1
- package/dist/actors/computer-use/loop/ending.d.ts +2 -2
- package/dist/actors/computer-use/loop/ending.js +2 -2
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +3 -3
- package/dist/actors/computer-use/loop/trace.js +2 -2
- package/dist/actors/computer-use/loop/types.d.ts +14 -5
- package/dist/actors/computer-use/loop.js +4 -4
- package/dist/actors/computer-use/openai-provider.d.ts +1 -1
- package/dist/actors/computer-use/openai-provider.js +2 -2
- package/dist/actors/contract.d.ts +10 -8
- package/dist/actors/contract.js +7 -1
- package/dist/actors/local-agent/cli.js +1 -1
- package/dist/actors/scripted-browser/actor.d.ts +2 -2
- package/dist/actors/scripted-browser/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +18 -0
- package/dist/actors/scripted-browser/types.d.ts +11 -1
- package/dist/actors/stop-conditions.js +1 -3
- package/dist/analysis/automatic-completion.d.ts +13 -8
- package/dist/analysis/automatic-completion.js +14 -8
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/analysis/automatic-config.js +2 -2
- package/dist/analysis/automatic.d.ts +10 -4
- package/dist/analysis/automatic.js +17 -13
- package/dist/analysis/diagnostics.d.ts +23 -0
- package/dist/analysis/diagnostics.js +112 -0
- package/dist/analysis/evidence-sources.js +2 -2
- package/dist/analysis/evidence.js +6 -6
- package/dist/analysis/execute.d.ts +7 -1
- package/dist/analysis/execute.js +39 -12
- package/dist/analysis/job.d.ts +8 -5
- package/dist/analysis/job.js +15 -14
- package/dist/analysis/load.d.ts +1 -1
- package/dist/analysis/load.js +5 -5
- package/dist/analysis/provider.d.ts +9 -1
- package/dist/analysis/restricted-codex.d.ts +2 -0
- package/dist/analysis/restricted-codex.js +10 -1
- package/dist/analysis/service.d.ts +2 -0
- package/dist/analysis/service.js +31 -12
- package/dist/analysis/sharing.d.ts +2 -2
- package/dist/analysis/sharing.js +5 -5
- package/dist/analysis/store-executions.d.ts +5 -5
- package/dist/analysis/store-executions.js +12 -12
- package/dist/analysis/store.d.ts +4 -4
- package/dist/analysis/store.js +13 -13
- package/dist/cli/commands/analysis-signals.d.ts +2 -1
- package/dist/cli/commands/analysis-signals.js +4 -1
- package/dist/cli/commands/analyze.js +4 -2
- package/dist/cli/commands/comms.js +8 -1
- package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +26 -14
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +3 -4
- package/dist/cli/commands/lab-route-run.d.ts +6 -4
- package/dist/cli/commands/lab-route-run.js +6 -2
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
- package/dist/cli/commands/lab-route-scripted.js +0 -1
- package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
- package/dist/cli/commands/lab-route-shared-world.js +0 -1
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
- package/dist/cli/commands/lab-route-terminal.js +0 -1
- package/dist/cli/commands/lab-run.js +76 -45
- package/dist/cli/commands/lab-scorer.d.ts +0 -2
- package/dist/cli/commands/lab.js +12 -6
- package/dist/cli/commands/observe.js +22 -0
- package/dist/cli/commands/run-signals.d.ts +30 -0
- package/dist/cli/commands/run-signals.js +146 -0
- package/dist/cli/commands/runs.js +10 -8
- package/dist/cli/commands/watch.js +12 -10
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.js +10 -2
- package/dist/cli/io.d.ts +5 -4
- package/dist/cli/io.js +12 -8
- package/dist/cli/program.js +3 -3
- package/dist/cli/renamed-options.d.ts +11 -0
- package/dist/cli/renamed-options.js +18 -0
- package/dist/cli/telemetry.d.ts +2 -2
- package/dist/cli/telemetry.js +1 -1
- package/dist/comms/capture-surface.d.ts +1 -1
- package/dist/comms/catch-host.d.ts +1 -1
- package/dist/comms/connections.js +4 -4
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- package/dist/comms/lease-store.js +7 -7
- package/dist/comms/types.js +1 -1
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- package/dist/evidence/redaction.js +1 -1
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +7 -9
- package/dist/feedback/export-bundle.js +4 -4
- package/dist/feedback/export.js +9 -9
- package/dist/feedback/feedback.d.ts +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +3 -6
- package/dist/keys/key-resolution.d.ts +3 -1
- package/dist/keys/key-resolution.js +18 -16
- package/dist/lab/adapter-extension.d.ts +28 -6
- package/dist/lab/adapter-extension.js +65 -126
- package/dist/lab/adapter-scorer-loader.d.ts +25 -5
- package/dist/lab/adapter-scorer-loader.js +24 -0
- package/dist/lab/composition-rules.d.ts +2 -0
- package/dist/lab/composition-rules.js +35 -26
- package/dist/lab/config.js +28 -26
- package/dist/lab/device-presets.d.ts +2 -2
- package/dist/lab/discover.js +1 -3
- package/dist/lab/doctor.d.ts +44 -9
- package/dist/lab/doctor.js +149 -41
- package/dist/lab/init-plan.js +1 -3
- package/dist/lab/keys.js +1 -1
- package/dist/lab/lab-deps.d.ts +85 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +8 -7
- package/dist/lab/parse/comms.js +3 -2
- package/dist/lab/parse/execution.js +3 -2
- package/dist/lab/parse/subject-state.js +2 -1
- package/dist/lab/parse/subject.js +2 -1
- package/dist/lab/parse/values.d.ts +0 -1
- package/dist/lab/parse/values.js +0 -3
- package/dist/lab/persona-resolve.d.ts +3 -3
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +6 -2
- package/dist/lab/plan-base.js +22 -7
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +33 -7
- package/dist/lab/plan.d.ts +3 -11
- package/dist/lab/plan.js +18 -42
- package/dist/lab/preflight-result.js +0 -2
- package/dist/lab/preflight.d.ts +0 -3
- package/dist/lab/preflight.js +1 -1
- package/dist/lab/requirements.d.ts +20 -0
- package/dist/lab/requirements.js +54 -0
- package/dist/lab/route-inputs.d.ts +23 -12
- package/dist/lab/route-inputs.js +48 -51
- package/dist/lab/routing.d.ts +19 -24
- package/dist/lab/routing.js +14 -47
- package/dist/lab/run-lab-events.d.ts +6 -11
- package/dist/lab/run-lab-events.js +3 -11
- package/dist/lab/run-lab-homes.d.ts +64 -0
- package/dist/lab/run-lab-homes.js +3 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +45 -275
- package/dist/lab/summary.d.ts +9 -4
- package/dist/lab/summary.js +15 -8
- package/dist/lab/types.d.ts +132 -132
- package/dist/lab/validation.d.ts +15 -15
- package/dist/lab/validation.js +28 -28
- package/dist/lab/warnings.js +20 -19
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +3 -3
- package/dist/observer/data.js +2 -2
- package/dist/observer/render.js +2 -2
- package/dist/observer/run-routes.d.ts +1 -1
- package/dist/observer/run-routes.js +5 -5
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +34 -3
- package/dist/observer-app.html +1 -1
- package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
- package/dist/routes/computer-use/bundle-parts.js +10 -3
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +9 -15
- package/dist/routes/computer-use/diagnostics.d.ts +1 -1
- package/dist/routes/computer-use/diagnostics.js +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
- package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
- package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +19 -43
- package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
- package/dist/routes/computer-use/fanout-bundle.js +25 -29
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
- package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
- package/dist/routes/computer-use/in-process-desktop.js +3 -9
- package/dist/routes/computer-use/live-flush.d.ts +7 -5
- package/dist/routes/computer-use/live-flush.js +19 -27
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
- package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
- package/dist/routes/computer-use/local-tree-pack.js +4 -5
- package/dist/routes/computer-use/local-vm.d.ts +11 -8
- package/dist/routes/computer-use/local-vm.js +39 -66
- package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
- package/dist/routes/computer-use/participant-desktop.js +5 -25
- package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
- package/dist/routes/computer-use/participant-facts.d.ts +7 -1
- package/dist/routes/computer-use/participant-facts.js +12 -1
- package/dist/routes/computer-use/participant-model.d.ts +19 -11
- package/dist/routes/computer-use/participant-model.js +58 -33
- package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
- package/dist/routes/computer-use/participant-prompt.js +4 -4
- package/dist/routes/computer-use/participant-runs.d.ts +6 -6
- package/dist/routes/computer-use/participant-runs.js +8 -8
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +59 -65
- package/dist/routes/computer-use/preflight.d.ts +6 -11
- package/dist/routes/computer-use/preflight.js +26 -18
- package/dist/routes/computer-use/rerun-selection.js +10 -6
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +40 -30
- package/dist/routes/computer-use/route.d.ts +3 -4
- package/dist/routes/computer-use/route.js +21 -19
- package/dist/routes/computer-use/self-report.d.ts +2 -2
- package/dist/routes/computer-use/self-report.js +4 -4
- package/dist/routes/computer-use/setup.d.ts +8 -17
- package/dist/routes/computer-use/setup.js +98 -86
- package/dist/routes/computer-use/single-bundle.d.ts +8 -11
- package/dist/routes/computer-use/single-bundle.js +20 -25
- package/dist/routes/computer-use/subject-projection.d.ts +5 -7
- package/dist/routes/computer-use/subject-projection.js +20 -19
- package/dist/routes/computer-use/types.d.ts +169 -211
- package/dist/routes/computer-use/types.js +13 -6
- package/dist/routes/preview.js +0 -1
- package/dist/routes/scripted/bundle.d.ts +3 -6
- package/dist/routes/scripted/bundle.js +11 -16
- package/dist/routes/scripted/plan.d.ts +5 -7
- package/dist/routes/scripted/plan.js +6 -4
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +10 -6
- package/dist/routes/scripted/route.js +10 -11
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +1 -1
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +22 -21
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +11 -6
- package/dist/routes/scripted/surface-records.js +1 -1
- package/dist/routes/scripted/surface-sessions.d.ts +2 -2
- package/dist/routes/scripted/surface-sessions.js +4 -4
- package/dist/routes/scripted/types.d.ts +19 -36
- package/dist/routes/scripted/types.js +1 -2
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
- package/dist/routes/shared-world/bundle.d.ts +2 -2
- package/dist/routes/shared-world/bundle.js +22 -26
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +4 -4
- package/dist/routes/shared-world/comms.d.ts +5 -4
- package/dist/routes/shared-world/comms.js +28 -41
- package/dist/routes/shared-world/external-public.d.ts +5 -5
- package/dist/routes/shared-world/external-public.js +19 -20
- package/dist/routes/shared-world/handoff.d.ts +4 -4
- package/dist/routes/shared-world/handoff.js +50 -50
- package/dist/routes/shared-world/lobby-code.d.ts +5 -5
- package/dist/routes/shared-world/lobby-code.js +13 -13
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +1 -2
- package/dist/routes/shared-world/provenance.d.ts +4 -4
- package/dist/routes/shared-world/provenance.js +4 -4
- package/dist/routes/shared-world/provisioned.d.ts +3 -2
- package/dist/routes/shared-world/provisioned.js +48 -41
- package/dist/routes/shared-world/result.js +31 -19
- package/dist/routes/shared-world/route.js +37 -41
- package/dist/routes/shared-world/setup.d.ts +5 -4
- package/dist/routes/shared-world/setup.js +12 -14
- package/dist/routes/shared-world/types.d.ts +53 -126
- package/dist/routes/shared-world/types.js +2 -2
- package/dist/routes/terminal/adapter.d.ts +8 -8
- package/dist/routes/terminal/adapter.js +28 -125
- package/dist/routes/terminal/bundle.d.ts +7 -12
- package/dist/routes/terminal/bundle.js +24 -34
- package/dist/routes/terminal/credentials.d.ts +2 -2
- package/dist/routes/terminal/credentials.js +16 -16
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +9 -11
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +6 -6
- package/dist/routes/terminal/ledger.js +9 -9
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +21 -20
- package/dist/routes/terminal/live-sandbox.d.ts +4 -2
- package/dist/routes/terminal/live-sandbox.js +25 -21
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +13 -9
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +4 -4
- package/dist/routes/terminal/route.js +26 -26
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +5 -3
- package/dist/routes/terminal/sandbox.js +13 -16
- package/dist/routes/terminal/session.js +16 -14
- package/dist/routes/terminal/token-usage.js +5 -5
- package/dist/routes/terminal/trace.d.ts +5 -8
- package/dist/routes/terminal/trace.js +9 -64
- package/dist/routes/terminal/types.d.ts +85 -93
- package/dist/routes/terminal/types.js +9 -4
- package/dist/run/active-runs.d.ts +13 -0
- package/dist/run/active-runs.js +12 -0
- package/dist/run/bundle-shape.d.ts +2 -1
- package/dist/run/bundle-shape.js +4 -4
- package/dist/run/bundle.d.ts +63 -56
- package/dist/run/bundle.js +9 -8
- package/dist/run/cost-summary.js +3 -2
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +10 -10
- package/dist/run/detail.d.ts +5 -5
- package/dist/run/detail.js +6 -6
- package/dist/run/dry-run.js +5 -12
- package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
- package/dist/run/{study-files.js → evidence-files.js} +5 -5
- package/dist/run/feedback-shape.js +1 -1
- package/dist/run/judge.d.ts +16 -4
- package/dist/run/judge.js +24 -7
- package/dist/run/locate.d.ts +2 -0
- package/dist/run/locate.js +3 -1
- package/dist/run/outcomes.d.ts +3 -3
- package/dist/run/outcomes.js +3 -3
- package/dist/run/participant-records.d.ts +2 -2
- package/dist/run/participant-records.js +2 -2
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +19 -9
- package/dist/run/pricing.js +30 -18
- package/dist/run/projection.d.ts +13 -13
- package/dist/run/projection.js +8 -8
- package/dist/run/reclaim.d.ts +7 -1
- package/dist/run/reclaim.js +24 -4
- package/dist/run/results.d.ts +1 -1
- package/dist/run/run-index.d.ts +1 -1
- package/dist/run/run-index.js +11 -11
- package/dist/run/run.d.ts +4 -2
- package/dist/run/run.js +9 -5
- package/dist/run/sandbox-receipts.d.ts +4 -4
- package/dist/run/sandbox-receipts.js +4 -4
- package/dist/run/shared-world-evidence.d.ts +47 -47
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +11 -11
- package/dist/run/stats.d.ts +5 -5
- package/dist/run/stats.js +8 -8
- package/dist/run/status.d.ts +16 -6
- package/dist/run/status.js +31 -8
- package/dist/run/streams.d.ts +26 -19
- package/dist/run/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/transient-comms-secrets.d.ts +5 -0
- package/dist/run/transient-comms-secrets.js +12 -0
- package/dist/run-lab.d.ts +36 -34
- package/dist/run-lab.js +41 -37
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +1 -1
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +2 -2
- package/dist/subject/local-tree.js +1 -1
- package/dist/subject/node-bootstrap.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +4 -4
- package/dist/subject/runtime.js +5 -5
- package/dist/subject/serve.js +1 -1
- package/dist/subject/steps.d.ts +4 -4
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/desktop-session.d.ts +2 -0
- package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
- package/dist/substrates/e2b/cdp-probe.js +1 -1
- package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
- package/dist/substrates/e2b/desktop-browser.js +4 -4
- package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
- package/dist/substrates/e2b/desktop-cdp.js +4 -4
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +3 -3
- package/dist/substrates/e2b/desktop-media.js +2 -2
- package/dist/substrates/e2b/sandbox.d.ts +2 -0
- package/dist/substrates/e2b/sandbox.js +22 -8
- package/dist/substrates/e2b/sdk.d.ts +12 -1
- package/dist/substrates/e2b/sdk.js +30 -9
- package/dist/substrates/local/runtime-host.d.ts +2 -0
- package/dist/substrates/local/runtime-host.js +6 -0
- package/dist/tui/actions.d.ts +7 -5
- package/dist/tui/actions.js +18 -9
- package/dist/tui-app.js +42 -42
- package/dist/verify/actor.d.ts +10 -10
- package/dist/verify/actor.js +15 -15
- package/dist/verify/artifacts.d.ts +1 -1
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/costs.d.ts +2 -2
- package/dist/verify/costs.js +2 -2
- package/dist/verify/liveness.d.ts +1 -1
- package/dist/verify/liveness.js +4 -1
- package/dist/verify/rerun.d.ts +1 -1
- package/dist/verify/rerun.js +1 -1
- package/dist/verify/shared-world.js +2 -2
- package/dist/verify/verify.js +6 -6
- package/docs/README.md +1 -1
- package/docs/architecture/actor-contract.md +60 -22
- package/docs/architecture/desktop-sessions.md +9 -9
- package/docs/architecture/external-public-shared-world.md +5 -0
- package/docs/architecture/observer.md +4 -4
- package/docs/architecture/restricted-codex-analysis.md +40 -4
- package/docs/architecture/state-driven-executor.md +4 -5
- package/docs/architecture/task-protocol-support.md +3 -5
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
- package/docs/contracts/run-bundle.md +10 -8
- package/docs/contracts/schemas.md +109 -53
- package/docs/contracts/study-analysis.md +24 -0
- package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- package/docs/product/automatic-analysis.md +1 -0
- package/docs/ramp/README.md +2 -1
- package/package.json +4 -4
- package/skills/humanish/SKILL.md +3 -2
- package/skills/humanish/agents/openai.yaml +1 -1
- package/dist/deprecated.d.ts +0 -90
- package/dist/deprecated.js +0 -106
- package/dist/lab/bag-overrides.d.ts +0 -18
- package/dist/lab/bag-overrides.js +0 -121
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -12,7 +12,7 @@ import { isNodeError } from "./type-guards.js";
|
|
|
12
12
|
* percent-decoded up to five times, and each round must still be a plain relative path, so an
|
|
13
13
|
* encoded `..` or separator cannot survive into a later decode.
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
15
|
+
export function isEvidencePath(value) {
|
|
16
16
|
return decodesToPlainRelativePath(value, 1024, /[\\:\x00-\x1f\x7f]|^\//);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
@@ -54,8 +54,8 @@ export function decodesToPlainRelativePath(value, maxLength, unsafe) {
|
|
|
54
54
|
* not turn an analysis budget into an unbounded read. No returned bytes have
|
|
55
55
|
* authority to select another file or initiate a network request.
|
|
56
56
|
*/
|
|
57
|
-
export async function
|
|
58
|
-
const result = await
|
|
57
|
+
export async function readBoundedFile(root, relativePath, maxBytes) {
|
|
58
|
+
const result = await readBoundedFileResult(root, relativePath, maxBytes);
|
|
59
59
|
return result.state === "read" ? result.bytes : null;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -89,8 +89,8 @@ export async function pathMissing(filePath) {
|
|
|
89
89
|
}
|
|
90
90
|
const unavailable = { state: "unavailable" };
|
|
91
91
|
/** Size refusals are distinguished only after the same contained regular-file checks. */
|
|
92
|
-
export async function
|
|
93
|
-
if (!
|
|
92
|
+
export async function readBoundedFileResult(root, relativePath, maxBytes) {
|
|
93
|
+
if (!isEvidencePath(relativePath) || !Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
94
94
|
return unavailable;
|
|
95
95
|
const validateRoot = async () => {
|
|
96
96
|
if ("physicalRunRoot" in root) {
|
|
@@ -31,7 +31,7 @@ export function isRunFeedbackCandidate(value) {
|
|
|
31
31
|
isFeedbackNextState(value.proposed_next_state) &&
|
|
32
32
|
Array.isArray(value.acceptance_proof) &&
|
|
33
33
|
value.acceptance_proof.every((item) => typeof item === "string") &&
|
|
34
|
-
// Optional, adapter-namespaced product-noun block: when present, validate only its
|
|
34
|
+
// Optional, adapter-namespaced product-noun block: when present, validate only its shape
|
|
35
35
|
// (a non-empty namespace + a data record). Core never inspects the keys inside `data`.
|
|
36
36
|
(value.adapter === undefined || isFeedbackAdapterBlock(value.adapter)));
|
|
37
37
|
}
|
package/dist/run/judge.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export declare function participantHarnessFailed(participant: ParticipantFacts):
|
|
|
60
60
|
* goal_satisfied claim with zero engagement is a session that ran out before anything happened;
|
|
61
61
|
* one whose final message describes a blocker is a participant who could not proceed and said so.
|
|
62
62
|
* Both keep their trace status (the claim is evidence); neither is a participant who reached the
|
|
63
|
-
* goal. One rule for the single
|
|
63
|
+
* goal. One rule for the single participant and the fan-out roll-up (#476).
|
|
64
64
|
*/
|
|
65
65
|
export declare function participantStatus(status: ActorStatus, judgments: {
|
|
66
66
|
noEngagement: boolean;
|
|
@@ -86,7 +86,7 @@ export interface Judgment {
|
|
|
86
86
|
/** The judgment for a verdict: a run passes when its verdict is pass, and a dry run passes. */
|
|
87
87
|
export declare function judgmentOf(verdict: Verdict, dryRun: boolean): Judgment;
|
|
88
88
|
/** What kind of execution failure a run recorded. */
|
|
89
|
-
type ExecutionFailureKind = "harness" | "provider-cleanup" | "sandbox-cleanup" | "evidence" | "cap" | "run";
|
|
89
|
+
type ExecutionFailureKind = "harness" | "provider-cleanup" | "provider-policy" | "sandbox-cleanup" | "evidence" | "cap" | "run";
|
|
90
90
|
/** One way the run failed as an execution. The message is scrubbed; status.json shows it. */
|
|
91
91
|
export interface ExecutionFailure {
|
|
92
92
|
kind: ExecutionFailureKind;
|
|
@@ -98,7 +98,19 @@ export interface ExecutionOutcome {
|
|
|
98
98
|
succeeded: boolean;
|
|
99
99
|
/** The failures the policy counts, in the order the route recorded them. */
|
|
100
100
|
failures: ExecutionFailure[];
|
|
101
|
+
/**
|
|
102
|
+
* The failures the policy lets warn, such as a sandbox whose release is unconfirmed on a route
|
|
103
|
+
* whose evidence stands. They leave `succeeded` and the result's ok alone but stay visible in
|
|
104
|
+
* status.json. Omitted when there are none.
|
|
105
|
+
*/
|
|
106
|
+
warnings?: ExecutionFailure[];
|
|
101
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* The execution failure for one sandbox whose release is unconfirmed. `warning` is the route's
|
|
110
|
+
* release warning, already scrubbed. `recovery` says how to release it by hand; without one,
|
|
111
|
+
* reclaim kills by the id the run recorded at create time.
|
|
112
|
+
*/
|
|
113
|
+
export declare function sandboxCleanupFailure(owner: string, warning: string | undefined, runId: string, recovery?: string): ExecutionFailure;
|
|
102
114
|
/**
|
|
103
115
|
* How a route turns the facts into its result's ok. A gate route needs every participant to
|
|
104
116
|
* pass. On an evidence route a participant that failed, was blocked or timed out is captured
|
|
@@ -131,7 +143,7 @@ export interface SharedWorldJudgment extends Judgment {
|
|
|
131
143
|
* A run with one participant: its tallied status is the verdict, so a hollow pass fails and a
|
|
132
144
|
* self-reported blocker reads as blocked. Without a session, a harness failure fails the run and
|
|
133
145
|
* a dry run is a contract. A run still in progress is a contract until it finishes. Computer-use
|
|
134
|
-
* calls it for one
|
|
146
|
+
* calls it for one participant with no rerun, and terminal calls it through judgeTerminal.
|
|
135
147
|
*/
|
|
136
148
|
export declare function judgeOneParticipant(args: {
|
|
137
149
|
dryRun: boolean;
|
|
@@ -195,7 +207,7 @@ export declare function judgePreview(): Judgment;
|
|
|
195
207
|
* stays as it was, so scoring can never improve a verdict. No failures returns the review as is.
|
|
196
208
|
*/
|
|
197
209
|
export declare function foldScorerFailures(review: ReviewSummary, failures: readonly string[]): ReviewSummary;
|
|
198
|
-
/** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is
|
|
210
|
+
/** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is a warning. */
|
|
199
211
|
export declare function judgeExecution(failures: readonly ExecutionFailure[], policy: OutcomePolicy): ExecutionOutcome;
|
|
200
212
|
/**
|
|
201
213
|
* The result's ok: the run worked as an execution, no scorer failed it, and on a gate route every
|
package/dist/run/judge.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// participantPassed, participantHarnessFailed);
|
|
7
7
|
// 2. the judgment shapes (Judgment and judgmentOf, SharedWorldJudgment, ExecutionOutcome,
|
|
8
8
|
// OutcomePolicy);
|
|
9
|
-
// 3. one judge per route: computer-use calls judgeOneParticipant (one
|
|
9
|
+
// 3. one judge per route: computer-use calls judgeOneParticipant (one participant, no rerun) or
|
|
10
10
|
// judgeParticipants, shared-world calls judgeSharedWorld, terminal calls judgeTerminal,
|
|
11
11
|
// scripted calls judgeScripted and preview calls judgePreview;
|
|
12
12
|
// 4. foldScorerFailures, which every route with a scorer applies before the run finishes;
|
|
@@ -65,7 +65,7 @@ export function participantHarnessFailed(participant) {
|
|
|
65
65
|
* goal_satisfied claim with zero engagement is a session that ran out before anything happened;
|
|
66
66
|
* one whose final message describes a blocker is a participant who could not proceed and said so.
|
|
67
67
|
* Both keep their trace status (the claim is evidence); neither is a participant who reached the
|
|
68
|
-
* goal. One rule for the single
|
|
68
|
+
* goal. One rule for the single participant and the fan-out roll-up (#476).
|
|
69
69
|
*/
|
|
70
70
|
export function participantStatus(status, judgments) {
|
|
71
71
|
if (status !== "passed" || judgments === undefined)
|
|
@@ -98,6 +98,17 @@ export function verdictForStatus(status) {
|
|
|
98
98
|
export function judgmentOf(verdict, dryRun) {
|
|
99
99
|
return { verdict, passed: dryRun || verdict === "pass" };
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* The execution failure for one sandbox whose release is unconfirmed. `warning` is the route's
|
|
103
|
+
* release warning, already scrubbed. `recovery` says how to release it by hand; without one,
|
|
104
|
+
* reclaim kills by the id the run recorded at create time.
|
|
105
|
+
*/
|
|
106
|
+
export function sandboxCleanupFailure(owner, warning, runId, recovery) {
|
|
107
|
+
return {
|
|
108
|
+
kind: "sandbox-cleanup",
|
|
109
|
+
message: `${owner}: ${warning ?? "Sandbox release is unconfirmed."} ${recovery ?? `Reclaim it by recorded id with \`humanish reclaim --run ${runId}\`.`}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
101
112
|
/** Each route's outcome policy, in one place. */
|
|
102
113
|
export const OUTCOME_POLICIES = {
|
|
103
114
|
"computer-use": { participants: "gate", sandboxCleanup: "warns", evidence: "fails" },
|
|
@@ -111,7 +122,7 @@ export const OUTCOME_POLICIES = {
|
|
|
111
122
|
* A run with one participant: its tallied status is the verdict, so a hollow pass fails and a
|
|
112
123
|
* self-reported blocker reads as blocked. Without a session, a harness failure fails the run and
|
|
113
124
|
* a dry run is a contract. A run still in progress is a contract until it finishes. Computer-use
|
|
114
|
-
* calls it for one
|
|
125
|
+
* calls it for one participant with no rerun, and terminal calls it through judgeTerminal.
|
|
115
126
|
*/
|
|
116
127
|
export function judgeOneParticipant(args) {
|
|
117
128
|
const status = args.participant === undefined ? undefined : judgedStatus(args.participant);
|
|
@@ -220,14 +231,20 @@ export function foldScorerFailures(review, failures) {
|
|
|
220
231
|
}
|
|
221
232
|
return folded;
|
|
222
233
|
}
|
|
223
|
-
/** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is
|
|
234
|
+
/** The run's execution outcome under its route's policy. A failure of a kind the policy lets warn is a warning. */
|
|
224
235
|
export function judgeExecution(failures, policy) {
|
|
225
|
-
const
|
|
236
|
+
const counts = (failure) => failure.kind === "sandbox-cleanup"
|
|
226
237
|
? policy.sandboxCleanup === "fails"
|
|
227
238
|
: failure.kind === "evidence"
|
|
228
239
|
? policy.evidence === "fails"
|
|
229
|
-
: true
|
|
230
|
-
|
|
240
|
+
: true;
|
|
241
|
+
const counted = failures.filter(counts);
|
|
242
|
+
const warnings = failures.filter((failure) => !counts(failure));
|
|
243
|
+
return {
|
|
244
|
+
succeeded: counted.length === 0,
|
|
245
|
+
failures: counted,
|
|
246
|
+
...(warnings.length === 0 ? {} : { warnings }),
|
|
247
|
+
};
|
|
231
248
|
}
|
|
232
249
|
/**
|
|
233
250
|
* The result's ok: the run worked as an execution, no scorer failed it, and on a gate route every
|
package/dist/run/locate.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { type PreparedRunArtifactPaths } from "./paths.js";
|
|
|
2
2
|
import { type PreparedSelectedOutputDirectory } from "./contained-output.js";
|
|
3
3
|
import type { RunPointer } from "./results.js";
|
|
4
4
|
import { type RunBundle } from "./bundle.js";
|
|
5
|
+
/** The run input that resolves through latest.json rather than naming a run directory. */
|
|
6
|
+
export declare const LATEST_RUN_ALIAS = "latest";
|
|
5
7
|
/** Resolve "latest" or an explicit run id to its prepared artifact paths. */
|
|
6
8
|
export declare function resolveRunPath(cwd: string, runInput: string): Promise<PreparedRunArtifactPaths | null>;
|
|
7
9
|
export declare function readLatest(runsRoot: PreparedSelectedOutputDirectory): Promise<RunPointer | null>;
|
package/dist/run/locate.js
CHANGED
|
@@ -5,9 +5,11 @@ import { assertPreparedSelectedOutputDirectory, bindExistingManagedHumanishOutpu
|
|
|
5
5
|
import { RUN_BUNDLE_FILE } from "./bundle.js";
|
|
6
6
|
import { isRunBundle, isRunPointer } from "./bundle-shape.js";
|
|
7
7
|
import { isNodeError } from "./type-guards.js";
|
|
8
|
+
/** The run input that resolves through latest.json rather than naming a run directory. */
|
|
9
|
+
export const LATEST_RUN_ALIAS = "latest";
|
|
8
10
|
/** Resolve "latest" or an explicit run id to its prepared artifact paths. */
|
|
9
11
|
export async function resolveRunPath(cwd, runInput) {
|
|
10
|
-
if (runInput ===
|
|
12
|
+
if (runInput === LATEST_RUN_ALIAS) {
|
|
11
13
|
const runsRoot = await bindExistingManagedHumanishOutputDirectory(cwd, "runs");
|
|
12
14
|
if (!runsRoot) {
|
|
13
15
|
return null;
|
package/dist/run/outcomes.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { type ActorStatus } from "../actors/contract.js";
|
|
2
2
|
import { type CuaGoalSource } from "../actors/goal-source.js";
|
|
3
3
|
import type { TaskFunnel } from "../lab/tasks.js";
|
|
4
|
-
import type { ParticipantOutcomes, ReviewSummary,
|
|
4
|
+
import type { ParticipantOutcomes, ReviewSummary, RunTaskFunnel } from "./bundle.js";
|
|
5
5
|
/** Tally participant outcomes from actor statuses. Statuses this does not recognise are counted in
|
|
6
6
|
* `total` but nowhere else, so the parts can never exceed the whole. */
|
|
7
7
|
export declare function tallyParticipantOutcomes(statuses: readonly ActorStatus[],
|
|
8
8
|
/** Per-participant: did this one report friction or a defect? Same order as `statuses`. */
|
|
9
9
|
reportedFriction?: readonly boolean[]): ParticipantOutcomes;
|
|
10
10
|
/** Roll per-participant funnels up into the study funnel. Undefined when nothing measured one. */
|
|
11
|
-
export declare function aggregateTaskFunnels(funnels: readonly TaskFunnel[]):
|
|
11
|
+
export declare function aggregateTaskFunnels(funnels: readonly TaskFunnel[]): RunTaskFunnel | undefined;
|
|
12
12
|
/** The funnel as one line, denominator on every number: `signup 2/2 · verify-email 1/2`. */
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function formatRunTaskFunnel(funnel: RunTaskFunnel): string;
|
|
14
14
|
type ParticipantOutcomeDetail = {
|
|
15
15
|
status: ActorStatus;
|
|
16
16
|
label?: string;
|
package/dist/run/outcomes.js
CHANGED
|
@@ -68,7 +68,7 @@ export function aggregateTaskFunnels(funnels) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
/** The funnel as one line, denominator on every number: `signup 2/2 · verify-email 1/2`. */
|
|
71
|
-
export function
|
|
71
|
+
export function formatRunTaskFunnel(funnel) {
|
|
72
72
|
if (funnel.tasks.length === 0)
|
|
73
73
|
return "no tasks declared";
|
|
74
74
|
return funnel.tasks
|
|
@@ -138,7 +138,7 @@ export function formatParticipantOutcomes(outcomes, terminalCauses = []) {
|
|
|
138
138
|
};
|
|
139
139
|
append(outcomes.abandoned, ["abandoned"], "gave up");
|
|
140
140
|
append(outcomes.ranOut, ["incomplete", "timed_out"], "interrupted (stop details unavailable)");
|
|
141
|
-
// "blocked" covers an approval the run could not give
|
|
141
|
+
// "blocked" covers an approval the run could not give and a blocker the participant reported in
|
|
142
142
|
// its own words, so the label names no cause.
|
|
143
143
|
if (outcomes.blocked > 0)
|
|
144
144
|
parts.push(`${outcomes.blocked} blocked`);
|
|
@@ -191,7 +191,7 @@ export function withCuaReviewProvenance(review, streams) {
|
|
|
191
191
|
const outcomes = formatParticipantOutcomes(review.participants, details);
|
|
192
192
|
// Preserve rerun context, participant narration and adapter-specific findings. Refreshing a
|
|
193
193
|
// historical summary qualifies its old tally instead of silently discarding that context.
|
|
194
|
-
const header = `Run gate: ${review.verdict}. Participants: ${outcomes}.${review.tasks ? ` Tasks: ${
|
|
194
|
+
const header = `Run gate: ${review.verdict}. Participants: ${outcomes}.${review.tasks ? ` Tasks: ${formatRunTaskFunnel(review.tasks)}.` : ""}`;
|
|
195
195
|
const prefix = `${header} Recorded summary: `;
|
|
196
196
|
const recorded = review.summary.startsWith(prefix)
|
|
197
197
|
? review.summary.slice(prefix.length)
|
|
@@ -12,7 +12,7 @@ export declare function participantIds(position: number): ParticipantIds;
|
|
|
12
12
|
/** A participant's record, at its 1-based place in the bundle, with its one stream. */
|
|
13
13
|
export declare function participantRecord(ids: ParticipantIds, place: number, fields: Omit<RunSimulation, "id" | "index" | "streamIds">): RunSimulation;
|
|
14
14
|
/**
|
|
15
|
-
* A participant's stream. `participantId` is the route's own participant id (a fan-out
|
|
15
|
+
* A participant's stream. `participantId` is the route's own participant id (a fan-out entry's `lane-NN` id),
|
|
16
16
|
* saved right after the record id when the route has one.
|
|
17
17
|
*/
|
|
18
18
|
export declare function participantStream(ids: ParticipantIds, fields: Omit<RunStream, "id" | "simId" | "laneId">, participantId?: string): RunStream;
|
|
@@ -24,5 +24,5 @@ export declare function participantResourceIds(ids: ParticipantIds, participantI
|
|
|
24
24
|
export declare function recordIdOf(stream: RunStream): string;
|
|
25
25
|
/** The record id a saved event names, when it names one. */
|
|
26
26
|
export declare function eventRecordIdOf(event: RunEvent): string | undefined;
|
|
27
|
-
/** The participant id an adapter recorded on a saved stream (a fan-out lane id), when it has one. */
|
|
27
|
+
/** The participant id an adapter recorded on a saved stream (a fan-out `lane-NN` id), when it has one. */
|
|
28
28
|
export declare function streamParticipantIdOf(stream: RunStream): string | undefined;
|
|
@@ -30,7 +30,7 @@ export function participantRecord(ids, place, fields) {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* A participant's stream. `participantId` is the route's own participant id (a fan-out
|
|
33
|
+
* A participant's stream. `participantId` is the route's own participant id (a fan-out entry's `lane-NN` id),
|
|
34
34
|
* saved right after the record id when the route has one.
|
|
35
35
|
*/
|
|
36
36
|
export function participantStream(ids, fields, participantId) {
|
|
@@ -57,7 +57,7 @@ export function recordIdOf(stream) {
|
|
|
57
57
|
export function eventRecordIdOf(event) {
|
|
58
58
|
return event.simId;
|
|
59
59
|
}
|
|
60
|
-
/** The participant id an adapter recorded on a saved stream (a fan-out lane id), when it has one. */
|
|
60
|
+
/** The participant id an adapter recorded on a saved stream (a fan-out `lane-NN` id), when it has one. */
|
|
61
61
|
export function streamParticipantIdOf(stream) {
|
|
62
62
|
return stream.laneId;
|
|
63
63
|
}
|
package/dist/run/paths.js
CHANGED
|
@@ -262,7 +262,7 @@ async function assertNoSymlinkDescendants(directory) {
|
|
|
262
262
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
263
263
|
for (const entry of entries) {
|
|
264
264
|
const child = path.join(directory, entry.name);
|
|
265
|
-
// A run directory can be written
|
|
265
|
+
// A run directory can be written concurrently with this walk: the atomic writer creates a
|
|
266
266
|
// `.humanish-write-*.tmp` sibling and renames it, and a run now also refreshes its own status
|
|
267
267
|
// record on a cadence. An entry that vanished between readdir and lstat therefore proves
|
|
268
268
|
// nothing except that it is gone, and a path that no longer exists cannot be a symlink escape:
|
package/dist/run/pricing.d.ts
CHANGED
|
@@ -10,12 +10,12 @@ export interface ModelRate {
|
|
|
10
10
|
* a reduced rate. Optional: absent means we do not model a discount and every input token is
|
|
11
11
|
* billed at `inputUsdPerToken`. */
|
|
12
12
|
cachedInputUsdPerToken?: number;
|
|
13
|
-
/** USD per input token newly
|
|
13
|
+
/** USD per input token newly written to the provider's prompt cache, when the provider bills
|
|
14
14
|
* writes (OpenAI: GPT-5.6+ bills `cache_write_tokens` at 1.25x the uncached input rate, as the
|
|
15
|
-
*
|
|
15
|
+
* total rate for those tokens, with no extra charge on top). Absent = writes are free (every
|
|
16
16
|
* pre-5.6 model) and any reported write tokens price at the plain input rate. */
|
|
17
17
|
cacheWriteUsdPerToken?: number;
|
|
18
|
-
/** Long-context tier, when the provider re-prices the
|
|
18
|
+
/** Long-context tier, when the provider re-prices the whole request past an input-size
|
|
19
19
|
* threshold (OpenAI GPT-5.6: >272K input tokens => 2x input-side, 1.5x output, full request).
|
|
20
20
|
* Priced exactly only when the usage carries per-request `turns` records; totals alone cannot
|
|
21
21
|
* say which requests crossed, so without turns the estimate stays on the short-context rate,
|
|
@@ -29,7 +29,7 @@ export interface ModelRate {
|
|
|
29
29
|
asOf: string;
|
|
30
30
|
/** Public pricing page the number came from (a comment/URL, never a secret). */
|
|
31
31
|
source: string;
|
|
32
|
-
/** true = a stand-in
|
|
32
|
+
/** true = a stand-in that was not copied from a live sheet; the estimate carries this flag so a
|
|
33
33
|
* placeholder rate is never mistaken for a confirmed one. */
|
|
34
34
|
placeholder?: boolean;
|
|
35
35
|
}
|
|
@@ -52,8 +52,8 @@ export interface DesktopResourceRate {
|
|
|
52
52
|
source: string;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
* The token-derived cost
|
|
56
|
-
* (unknown rate or no token usage)
|
|
55
|
+
* The token-derived cost estimate for one actor trace. `estimatedCostUsd: null` = declared absent
|
|
56
|
+
* (unknown rate or no token usage) and is never coerced to 0. A non-null figure always carries its
|
|
57
57
|
* pricing provenance (`ratesAsOf` + `source`) so the mechanism (a rate-table multiply) matches
|
|
58
58
|
* the claim (an estimate, not a charge). Defined here so the rate table and the field that
|
|
59
59
|
* consumes it live together; `ActorTrace` imports it type-only.
|
|
@@ -71,13 +71,17 @@ export interface ActorEstimatedCost {
|
|
|
71
71
|
modelId?: string;
|
|
72
72
|
/** true when the rate is a stand-in, not a live sheet. */
|
|
73
73
|
placeholder?: boolean;
|
|
74
|
+
/** Set when usage arrived as runtime-turn totals that each sum several requests. No request's
|
|
75
|
+
* own size is known, so no per-request long-context tier was applied: tokens are priced at the
|
|
76
|
+
* base tier, cached input at the cached rate. */
|
|
77
|
+
basis?: "aggregated_turns_base_rate";
|
|
74
78
|
breakdown?: {
|
|
75
79
|
inputUsd: number;
|
|
76
80
|
outputUsd: number;
|
|
77
81
|
inputTokens: number;
|
|
78
82
|
outputTokens: number;
|
|
79
83
|
/** Of `inputTokens`, how many were billed at the reduced cached rate. Present only when the
|
|
80
|
-
* provider reported cache hits
|
|
84
|
+
* provider reported cache hits and the rate sheet models a cached rate. */
|
|
81
85
|
cachedInputTokens?: number;
|
|
82
86
|
/** Of `inputTokens`, how many were billed at the cache-WRITE rate (OpenAI 5.6+). */
|
|
83
87
|
cacheWriteInputTokens?: number;
|
|
@@ -86,7 +90,7 @@ export interface ActorEstimatedCost {
|
|
|
86
90
|
longContextTurns?: number;
|
|
87
91
|
};
|
|
88
92
|
}
|
|
89
|
-
/** The desktop-minute cost
|
|
93
|
+
/** The desktop-minute cost estimate (host-side create->teardown span * a per-minute rate). Same
|
|
90
94
|
* null-discipline as ActorEstimatedCost: `estimatedCostUsd: null` = not measured (no duration). */
|
|
91
95
|
export interface DesktopCostEstimate {
|
|
92
96
|
estimatedCostUsd: number | null;
|
|
@@ -108,13 +112,19 @@ export declare function estimateAllocatedDesktopCost(minutes: number | undefined
|
|
|
108
112
|
* precision. */
|
|
109
113
|
export declare function round6(n: number): number;
|
|
110
114
|
/**
|
|
111
|
-
* Estimate one actor
|
|
115
|
+
* Estimate one actor trace's model-token cost from its trace tokenUsage + model id. Deterministic;
|
|
112
116
|
* the rate table is injectable (tests pass a fake sheet). Returns a DECLARED-ABSENT estimate
|
|
113
117
|
* (estimatedCostUsd: null + a reason) for a missing rate or missing usage — never a guessed cost.
|
|
114
118
|
*/
|
|
115
119
|
export declare function estimateActorCostForExecution(usage: ActorTokenUsage | undefined, modelId: string | undefined, profile?: {
|
|
116
120
|
billing?: unknown;
|
|
117
121
|
}): ActorEstimatedCost;
|
|
122
|
+
/**
|
|
123
|
+
* Price usage reported as runtime-turn totals, such as Codex `turn.completed`, which sums every
|
|
124
|
+
* request in the turn. Pricing a turn as one request would apply the long-context tier to the
|
|
125
|
+
* whole turn, so the per-turn records are dropped and the totals price on the base tier.
|
|
126
|
+
*/
|
|
127
|
+
export declare function estimateAggregatedTurnCost(tokenUsage: ActorTokenUsage | undefined, modelId: string | undefined): ActorEstimatedCost;
|
|
118
128
|
export declare function estimateActorCost(tokenUsage: ActorTokenUsage | undefined, modelId: string | undefined, rates?: Record<string, ModelRate>): ActorEstimatedCost;
|
|
119
129
|
/**
|
|
120
130
|
* Estimate the E2B desktop-minute cost from a host-side create->teardown span (minutes). The rate
|
package/dist/run/pricing.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
//
|
|
2
|
-
// notice. When they do, update
|
|
3
|
-
// Every dollar figure humanish derives from this table is surfaced/persisted as an
|
|
4
|
-
// labeled "estimated (rates as of <asOf>)", and is
|
|
1
|
+
// Operator-editable estimates, which are not authoritative prices. Providers change pricing without
|
|
2
|
+
// notice. When they do, update both the number and the `asOf` date on the affected entry.
|
|
3
|
+
// Every dollar figure humanish derives from this table is surfaced/persisted as an estimate,
|
|
4
|
+
// labeled "estimated (rates as of <asOf>)", and is never presented as an exact charge.
|
|
5
5
|
//
|
|
6
|
-
// This module is
|
|
7
|
-
// an
|
|
8
|
-
// on the live numbers below. An
|
|
9
|
-
// (estimatedCostUsd: null + a reason)
|
|
6
|
+
// This module is pure (node builtins only, no deps) and deterministic: the estimator functions take
|
|
7
|
+
// an optional injected rate table/rate so tests drive assertions with a fake sheet and never depend
|
|
8
|
+
// on the live numbers below. An unknown model/desktop rate yields a declared-absent estimate
|
|
9
|
+
// (estimatedCostUsd: null + a reason) and never a guessed or silent-zero cost (invariant 5). A bare
|
|
10
10
|
// `costUsd` elsewhere in the contract means a provider actually billed that amount; the
|
|
11
11
|
// token-derived estimate here always lives under `estimatedCostUsd` so a reader can never confuse
|
|
12
12
|
// an estimate for an authoritative charge (invariant 6).
|
|
13
13
|
export const PRICING_SCHEMA = "humanish.pricing.v1";
|
|
14
14
|
export const ACTOR_ESTIMATED_COST_SCHEMA = "humanish.actor-estimated-cost.v1";
|
|
15
|
-
// The gpt-5.6 long-context tier: >272K input tokens re-prices the
|
|
15
|
+
// The gpt-5.6 long-context tier: >272K input tokens re-prices the full request at 2x
|
|
16
16
|
// input-side / 1.5x output (developers.openai.com/api/docs/models/gpt-5.6-sol, 2026-08-18).
|
|
17
17
|
const LONG_CONTEXT_TIER_272K = {
|
|
18
18
|
thresholdInputTokens: 272_000,
|
|
@@ -41,7 +41,7 @@ function rateWithLongContextTier(inPer1M, cachedPer1M, writePer1M, outPer1M, asO
|
|
|
41
41
|
const GPT56_SOL_PROMO_AS_OF = "2026-09-03";
|
|
42
42
|
const GPT6_ASTRA_AS_OF = "2026-09-03";
|
|
43
43
|
// Per-model rates, keyed on the model id that lands in trace.ids.model (lookup is
|
|
44
|
-
// case-insensitive on a trimmed id). An id
|
|
44
|
+
// case-insensitive on a trimmed id). An id missing here is declared absent, never guessed.
|
|
45
45
|
export const MODEL_RATES = {
|
|
46
46
|
// OpenAI computer-use-preview (the classic CUA model). ~$3 / 1M input, ~$12 / 1M output.
|
|
47
47
|
// source: openai.com/api/pricing (verify — providers change without notice).
|
|
@@ -74,7 +74,7 @@ export const MODEL_RATES = {
|
|
|
74
74
|
"gpt-5.6-cyber": rateWithLongContextTier(12.5, 1.25, 15.625, 75),
|
|
75
75
|
// Daybreak program aliases (blue -> sol, red -> cyber today). OpenAI repoints these as new
|
|
76
76
|
// frontier models ship, so prefer the explicit tier id in labs; the entries exist so a
|
|
77
|
-
// configured alias still prices at what the alias bills
|
|
77
|
+
// configured alias still prices at what the alias bills today.
|
|
78
78
|
"daybreak-blue-latest": rateWithLongContextTier(4, 0.4, 5, 20, GPT56_SOL_PROMO_AS_OF),
|
|
79
79
|
"daybreak-red-latest": rateWithLongContextTier(12.5, 1.25, 15.625, 75),
|
|
80
80
|
// gpt-6-astra (shipped 2026-09-03; API access announced as rolling out). Same two mechanics
|
|
@@ -157,7 +157,7 @@ export function round6(n) {
|
|
|
157
157
|
return Math.round(n * 1e6) / 1e6;
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
160
|
-
* Estimate one actor
|
|
160
|
+
* Estimate one actor trace's model-token cost from its trace tokenUsage + model id. Deterministic;
|
|
161
161
|
* the rate table is injectable (tests pass a fake sheet). Returns a DECLARED-ABSENT estimate
|
|
162
162
|
* (estimatedCostUsd: null + a reason) for a missing rate or missing usage — never a guessed cost.
|
|
163
163
|
*/
|
|
@@ -172,6 +172,18 @@ export function estimateActorCostForExecution(usage, modelId, profile) {
|
|
|
172
172
|
}
|
|
173
173
|
: estimateActorCost(usage, modelId);
|
|
174
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Price usage reported as runtime-turn totals, such as Codex `turn.completed`, which sums every
|
|
177
|
+
* request in the turn. Pricing a turn as one request would apply the long-context tier to the
|
|
178
|
+
* whole turn, so the per-turn records are dropped and the totals price on the base tier.
|
|
179
|
+
*/
|
|
180
|
+
export function estimateAggregatedTurnCost(tokenUsage, modelId) {
|
|
181
|
+
const { turns: _turns, ...totals } = tokenUsage ?? {};
|
|
182
|
+
const estimate = estimateActorCost(tokenUsage === undefined ? undefined : totals, modelId);
|
|
183
|
+
return estimate.estimatedCostUsd === null
|
|
184
|
+
? estimate
|
|
185
|
+
: { ...estimate, basis: "aggregated_turns_base_rate" };
|
|
186
|
+
}
|
|
175
187
|
export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
|
|
176
188
|
if (!tokenUsage || (tokenUsage.input === undefined && tokenUsage.output === undefined)) {
|
|
177
189
|
return {
|
|
@@ -193,15 +205,15 @@ export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
|
|
|
193
205
|
}
|
|
194
206
|
const inTok = tokenUsage.input ?? 0;
|
|
195
207
|
const outTok = tokenUsage.output ?? 0;
|
|
196
|
-
// Long-context tiering needs to know each
|
|
197
|
-
// requests past the threshold), so it engages only when per-turn usage records exist
|
|
208
|
+
// Long-context tiering needs to know each request's input size (the provider re-prices whole
|
|
209
|
+
// requests past the threshold), so it engages only when per-turn usage records exist and their
|
|
198
210
|
// input sums to the reported total — a partial turn ledger must not silently price the missing
|
|
199
211
|
// remainder at the wrong tier. Otherwise totals price on the base (short-context) rate, which is
|
|
200
212
|
// the under-estimate direction and never trips a cap early.
|
|
201
213
|
const turns = tokenUsage.turns ?? [];
|
|
202
214
|
const sumOf = (field) => turns.reduce((sum, turn) => sum + (turn[field] ?? 0), 0);
|
|
203
|
-
// The ledger is trusted only when it decomposes the totals
|
|
204
|
-
//
|
|
215
|
+
// The ledger is trusted only when it decomposes the totals exactly, in all four sums including the
|
|
216
|
+
// cache splits. A ledger that carries request sizes but not the cache splits would otherwise
|
|
205
217
|
// price every token at the full rate while the session totals sit ignored, overstating spend
|
|
206
218
|
// 3.5-5x and tripping caps early. Inconsistent evidence falls back to the totals path, which
|
|
207
219
|
// honors the declared splits on the base tier.
|
|
@@ -217,8 +229,8 @@ export function estimateActorCost(tokenUsage, modelId, rates = MODEL_RATES) {
|
|
|
217
229
|
let writeTotal = 0;
|
|
218
230
|
let longContextTurns = 0;
|
|
219
231
|
// Price one request's usage at one tier. Cached input is billed at a fraction of the full rate,
|
|
220
|
-
// and on a session that threads provider state it is the
|
|
221
|
-
// full rate overstates real spend by up to ~10x. Cache
|
|
232
|
+
// and on a session that threads provider state it is the majority of input, and pricing it at the
|
|
233
|
+
// full rate overstates real spend by up to ~10x. Cache writes bill at their own rate (1.25x on
|
|
222
234
|
// OpenAI 5.6+) as the total rate for those tokens; a sheet without a write rate prices writes as
|
|
223
235
|
// plain input (pre-5.6: writes are free-of-extra-fee, i.e. plain input). Every piece is honestly
|
|
224
236
|
// absent: no reported split means no discount and no surcharge assumed.
|
package/dist/run/projection.d.ts
CHANGED
|
@@ -40,11 +40,11 @@ export interface LabExpectation {
|
|
|
40
40
|
costUnknown: number;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Derive what to expect from a lab's own history. Only
|
|
43
|
+
* Derive what to expect from a lab's own history. Only finished runs count: an interrupted run's
|
|
44
44
|
* duration is the length of an accident, not of a study, and including it would quietly bias the
|
|
45
45
|
* estimate the operator uses to decide whether to press Start.
|
|
46
46
|
*
|
|
47
|
-
*
|
|
47
|
+
* The mode matters: mixing modes produces a false figure. A dry run spends nothing and
|
|
48
48
|
* takes no time, so a median over nine dry runs and one live one reports that a live run is free —
|
|
49
49
|
* next to a control that spends money. Pass the mode the figure is about; omit it only for a
|
|
50
50
|
* summary that is not attached to an action.
|
|
@@ -59,7 +59,7 @@ export declare function expectationLine(expectation: LabExpectation): string;
|
|
|
59
59
|
/**
|
|
60
60
|
* The one line a lab may say about itself, wherever it is shown.
|
|
61
61
|
*
|
|
62
|
-
* Prefers
|
|
62
|
+
* Prefers live figures: cost and duration are what someone reads before spending, and a median
|
|
63
63
|
* diluted by dry runs reports a live study as cheaper and faster than it has ever been. With no
|
|
64
64
|
* live history it reports the count and claims nothing about time or money — which is why this is
|
|
65
65
|
* shared rather than reimplemented per surface, since the two disagreeing is the whole failure.
|
|
@@ -104,15 +104,15 @@ export declare function livenessLabel(entry: Pick<RunIndexEntry, "liveness" | "v
|
|
|
104
104
|
/** A lab as the labs list shows it: what is declared, joined to what actually happened. */
|
|
105
105
|
export interface LabRow {
|
|
106
106
|
/**
|
|
107
|
-
* Stable identity for
|
|
107
|
+
* Stable identity for this row. A manifest's path when it has one, else the lab id, because two
|
|
108
108
|
* manifests can declare the same id, and keying rows by id makes them collapse into a pair of
|
|
109
109
|
* indistinguishable duplicates.
|
|
110
110
|
*/
|
|
111
111
|
key: string;
|
|
112
|
-
/** The declared id. Run history attributes to this, so it is
|
|
112
|
+
/** The declared id. Run history attributes to this, so it is not unique across manifests. */
|
|
113
113
|
labId: string;
|
|
114
114
|
/**
|
|
115
|
-
* The handle an operator would actually type. Lab resolution is by
|
|
115
|
+
* The handle an operator would actually type. Lab resolution is by filename, so the manifest
|
|
116
116
|
* `\`.humanish/labs/persona-contrast-live.yaml\`` is reached as `persona-contrast-live` even when
|
|
117
117
|
* the id inside it says something else.
|
|
118
118
|
*/
|
|
@@ -120,25 +120,25 @@ export interface LabRow {
|
|
|
120
120
|
/** The manifest's own title, when it has one. */
|
|
121
121
|
title?: string;
|
|
122
122
|
/**
|
|
123
|
-
* The shortest label that is
|
|
123
|
+
* The shortest label that is unique among the rows it is listed with: the title when no other
|
|
124
124
|
* lab shares it, else the filename, else the full path. A list is only navigable if every row can
|
|
125
125
|
* be told from every other one, and a title is not guaranteed to be distinct — two manifests in
|
|
126
|
-
* this repo carry the same title
|
|
126
|
+
* this repo carry the same title and the same declared id, differing only by filename.
|
|
127
127
|
*/
|
|
128
128
|
label: string;
|
|
129
|
-
/** The manifest's own words, for the list to say what this study
|
|
129
|
+
/** The manifest's own words, for the list to say what this study is. */
|
|
130
130
|
description?: string;
|
|
131
131
|
/** Repo-relative manifest path, absent for a lab known only from run history. */
|
|
132
132
|
path?: string;
|
|
133
133
|
origin?: "committed" | "ignored" | "explicit";
|
|
134
134
|
/**
|
|
135
|
-
* False for a lab that has runs but
|
|
135
|
+
* False for a lab that has runs but no manifest here: renamed, deleted, or run from a path that
|
|
136
136
|
* is gone. Its runs are still evidence and must stay reachable, so it is listed and marked rather
|
|
137
137
|
* than dropped.
|
|
138
138
|
*/
|
|
139
139
|
declared: boolean;
|
|
140
140
|
/**
|
|
141
|
-
* How many
|
|
141
|
+
* How many other manifests declare this same lab id. Above zero, the run history below is shared
|
|
142
142
|
* between them and cannot be attributed to one file — worth saying, because it is a
|
|
143
143
|
* misconfiguration the operator almost certainly does not know about.
|
|
144
144
|
*/
|
|
@@ -169,13 +169,13 @@ export interface DeclaredLab {
|
|
|
169
169
|
* deleted — that evidence still exists on disk, so dropping those rows would make real runs
|
|
170
170
|
* unreachable from the surface that is supposed to list them.
|
|
171
171
|
*
|
|
172
|
-
*
|
|
172
|
+
* One row per manifest, not per id. The two are not the same thing: a manifest is addressed by its
|
|
173
173
|
* filename while its runs attribute to the id declared inside it, so several files can legitimately
|
|
174
174
|
* share an id. Collapsing them hides a real file; keying by id duplicates a row with no way to tell
|
|
175
175
|
* the copies apart. Both happen in practice — this repo has exactly that pair.
|
|
176
176
|
*
|
|
177
177
|
* Order puts a lab someone is working in first, then labs by how recently they ran, then declared
|
|
178
|
-
* labs that have never run (alphabetically
|
|
178
|
+
* labs that have never run (alphabetically by the displayed label, so the order on screen is the
|
|
179
179
|
* order a reader can predict), then labs known only from history.
|
|
180
180
|
*/
|
|
181
181
|
export declare function labRows(declared: readonly DeclaredLab[], entries: readonly RunIndexEntry[]): {
|