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
package/dist/run/stats.js
CHANGED
|
@@ -5,12 +5,10 @@ import path from "node:path";
|
|
|
5
5
|
import { readRunIndex } from "./run-index.js";
|
|
6
6
|
import { addCostTotals, emptyCostTotals, readCostTotals, } from "./costs.js";
|
|
7
7
|
import { round6 } from "./pricing.js";
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"Analysis is attributed to its run's start date, including later reruns. " +
|
|
13
|
-
"JSON estimatedSpendUsd and medianCostUsd retain their participant/desktop-only meaning; costs includes analysis.";
|
|
8
|
+
import { plural } from "./text.js";
|
|
9
|
+
const STATS_SCHEMA = "humanish.stats.v2";
|
|
10
|
+
// docs/contracts/study-costs.md holds the accounting rules this sentence summarizes.
|
|
11
|
+
const STATS_NOTE = "Dollar figures are estimates from humanish's rate table, never provider charges, and a cost humanish does not know is left out of every total.";
|
|
14
12
|
function median(values) {
|
|
15
13
|
if (values.length === 0)
|
|
16
14
|
return undefined;
|
|
@@ -28,15 +26,26 @@ function addParticipants(into, entry) {
|
|
|
28
26
|
into.reachedGoal += entry.participants.reachedGoal;
|
|
29
27
|
into.reportedFriction += entry.participants.reportedFriction ?? 0;
|
|
30
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* A run's participant and desktop estimate: its recorded figure, or $0 for a dry run that records
|
|
31
|
+
* none, since a dry run makes no model request and creates no desktop. Undefined when the cost is
|
|
32
|
+
* unknown, including a dry run that records an unknown (null) figure.
|
|
33
|
+
*/
|
|
34
|
+
function runEstimateUsd(entry) {
|
|
35
|
+
const usd = entry.estimatedCostUsd;
|
|
36
|
+
if (typeof usd === "number" && Number.isFinite(usd) && usd >= 0)
|
|
37
|
+
return usd;
|
|
38
|
+
return usd === undefined && entry.mode === "dry-run" ? 0 : undefined;
|
|
39
|
+
}
|
|
31
40
|
function entryTime(entry) {
|
|
32
41
|
return entry.startedAt ?? entry.completedAt ?? entry.updatedAt;
|
|
33
42
|
}
|
|
34
|
-
function addToLabRow(labs, entry,
|
|
35
|
-
const labId = entry.
|
|
43
|
+
function addToLabRow(labs, entry, runUsd, costs) {
|
|
44
|
+
const labId = entry.study?.id ?? "(no study)";
|
|
36
45
|
let row = labs.get(labId);
|
|
37
46
|
if (row === undefined) {
|
|
38
47
|
row = {
|
|
39
|
-
|
|
48
|
+
study: labId,
|
|
40
49
|
runs: 0,
|
|
41
50
|
live: 0,
|
|
42
51
|
dryRun: 0,
|
|
@@ -64,14 +73,14 @@ function addToLabRow(labs, entry, priced, costs) {
|
|
|
64
73
|
}
|
|
65
74
|
if (entry.mode === "live" && entry.durationMs !== undefined)
|
|
66
75
|
row.durations.push(entry.durationMs);
|
|
67
|
-
if (
|
|
68
|
-
row.runCosts.push(entry.estimatedCostUsd);
|
|
69
|
-
else
|
|
76
|
+
if (runUsd === undefined)
|
|
70
77
|
row.unpricedRuns += 1;
|
|
78
|
+
else
|
|
79
|
+
row.runCosts.push(runUsd);
|
|
71
80
|
addParticipants(row.participants, entry);
|
|
72
81
|
addCostTotals(row.costs, costs);
|
|
73
82
|
}
|
|
74
|
-
function addToDayRow(days, entry,
|
|
83
|
+
function addToDayRow(days, entry, runUsd, costs) {
|
|
75
84
|
const at = entryTime(entry);
|
|
76
85
|
const day = at === undefined ? "(undated)" : at.slice(0, 10);
|
|
77
86
|
let dayRow = days.get(day);
|
|
@@ -89,10 +98,10 @@ function addToDayRow(days, entry, priced, costs) {
|
|
|
89
98
|
dayRow.runs += 1;
|
|
90
99
|
if (entry.mode === "live")
|
|
91
100
|
dayRow.live += 1;
|
|
92
|
-
if (
|
|
93
|
-
dayRow.estimatedSpendUsd += entry.estimatedCostUsd;
|
|
94
|
-
else
|
|
101
|
+
if (runUsd === undefined)
|
|
95
102
|
dayRow.unpricedRuns += 1;
|
|
103
|
+
else
|
|
104
|
+
dayRow.estimatedSpendUsd += runUsd;
|
|
96
105
|
addCostTotals(dayRow.costs, costs);
|
|
97
106
|
}
|
|
98
107
|
export async function computeStats(cwdInput, options = {}) {
|
|
@@ -127,7 +136,7 @@ export async function computeStats(cwdInput, options = {}) {
|
|
|
127
136
|
})),
|
|
128
137
|
];
|
|
129
138
|
const selected = entries.filter((entry) => {
|
|
130
|
-
if (options.lab !== undefined && entry.
|
|
139
|
+
if (options.lab !== undefined && entry.study?.id !== options.lab)
|
|
131
140
|
return false;
|
|
132
141
|
if (sinceMs !== undefined) {
|
|
133
142
|
const at = entryTime(entry);
|
|
@@ -164,18 +173,16 @@ export async function computeStats(cwdInput, options = {}) {
|
|
|
164
173
|
totals.dryRun += 1;
|
|
165
174
|
if (entry.liveness === "running")
|
|
166
175
|
totals.running += 1;
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
entry.estimatedCostUsd >= 0;
|
|
170
|
-
if (priced)
|
|
171
|
-
totals.estimatedSpendUsd += entry.estimatedCostUsd;
|
|
172
|
-
else
|
|
176
|
+
const runUsd = runEstimateUsd(entry);
|
|
177
|
+
if (runUsd === undefined)
|
|
173
178
|
totals.unpricedRuns += 1;
|
|
179
|
+
else
|
|
180
|
+
totals.estimatedSpendUsd += runUsd;
|
|
174
181
|
addParticipants(totals.participants, entry);
|
|
175
182
|
if (entry.verdict !== undefined)
|
|
176
183
|
totals.verdicts[entry.verdict] = (totals.verdicts[entry.verdict] ?? 0) + 1;
|
|
177
|
-
addToLabRow(labs, entry,
|
|
178
|
-
addToDayRow(days, entry,
|
|
184
|
+
addToLabRow(labs, entry, runUsd, accounting.costs);
|
|
185
|
+
addToDayRow(days, entry, runUsd, accounting.costs);
|
|
179
186
|
}
|
|
180
187
|
const labRows = [...labs.values()]
|
|
181
188
|
.map(({ durations, runCosts, ...row }) => ({
|
|
@@ -186,15 +193,15 @@ export async function computeStats(cwdInput, options = {}) {
|
|
|
186
193
|
...(runCosts.length === 0 ? {} : { medianCostUsd: round6(median(runCosts)) }),
|
|
187
194
|
costSamples: runCosts.length,
|
|
188
195
|
}))
|
|
189
|
-
.sort((a, b) => b.runs - a.runs || a.
|
|
196
|
+
.sort((a, b) => b.runs - a.runs || a.study.localeCompare(b.study));
|
|
190
197
|
return {
|
|
191
198
|
schema: STATS_SCHEMA,
|
|
192
199
|
ok: true,
|
|
193
200
|
cwd,
|
|
194
201
|
...(options.since === undefined ? {} : { since: options.since }),
|
|
195
|
-
...(options.lab === undefined ? {} : {
|
|
202
|
+
...(options.lab === undefined ? {} : { study: options.lab }),
|
|
196
203
|
totals: { ...totals, estimatedSpendUsd: round6(totals.estimatedSpendUsd) },
|
|
197
|
-
|
|
204
|
+
studies: labRows,
|
|
198
205
|
days: [...days.values()]
|
|
199
206
|
.map((row) => ({ ...row, estimatedSpendUsd: round6(row.estimatedSpendUsd) }))
|
|
200
207
|
.sort((a, b) => a.day.localeCompare(b.day)),
|
|
@@ -212,47 +219,98 @@ function knownMoney(value) {
|
|
|
212
219
|
function minutes(ms) {
|
|
213
220
|
return `${(ms / 60_000).toFixed(1)}m`;
|
|
214
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Whether every selected run is a dry run whose accounting is a complete $0: no recorded figure,
|
|
224
|
+
* no incomplete estimate and no analysis attempt. Only then does the one-line report hold.
|
|
225
|
+
*/
|
|
226
|
+
function onlyFreeDryRuns(t) {
|
|
227
|
+
return (t.runs > 0 &&
|
|
228
|
+
t.runs === t.dryRun &&
|
|
229
|
+
t.costs.estimatedTotalUsd === 0 &&
|
|
230
|
+
t.costs.incompleteRunEstimates === 0 &&
|
|
231
|
+
t.costs.analysisAttempts === 0);
|
|
232
|
+
}
|
|
233
|
+
/** The run counts, with dry runs on their own line. */
|
|
234
|
+
function runCountLines(t) {
|
|
235
|
+
if (t.runs === 0)
|
|
236
|
+
return ["no runs yet; start one with humanish run first-run"];
|
|
237
|
+
if (onlyFreeDryRuns(t))
|
|
238
|
+
return [`${plural(t.dryRun, "dry run")} ($0); no live runs yet`];
|
|
239
|
+
const running = t.running > 0 ? ` (${t.running} still running)` : "";
|
|
240
|
+
return [`live runs: ${t.live}${running}`, ...(t.dryRun > 0 ? [`dry runs: ${t.dryRun}`] : [])];
|
|
241
|
+
}
|
|
242
|
+
/** Spend, analysis, participants and verdicts across the selected live runs. */
|
|
243
|
+
function totalsLines(t) {
|
|
244
|
+
const c = t.costs;
|
|
245
|
+
const incomplete = c.incompleteRunEstimates > 0
|
|
246
|
+
? `; ${plural(c.incompleteRunEstimates, "run")} with incomplete accounting`
|
|
247
|
+
: "";
|
|
248
|
+
const unpriced = c.analysisUnpricedAttempts > 0 || c.analysisUnresolvedAttempts > 0
|
|
249
|
+
? `; ${c.analysisUnpricedAttempts} unpriced, ${c.analysisUnresolvedAttempts} unresolved`
|
|
250
|
+
: "";
|
|
251
|
+
const verdicts = Object.entries(t.verdicts).map(([verdict, count]) => `${verdict} ${count}`);
|
|
252
|
+
return [
|
|
253
|
+
`known estimated spend: ${knownMoney(c.estimatedTotalUsd)}`,
|
|
254
|
+
`participants and desktops: ${knownMoney(c.runEstimatedUsd)}${incomplete}`,
|
|
255
|
+
c.analysisAttempts === 0
|
|
256
|
+
? "analysis: none recorded"
|
|
257
|
+
: `analysis: ${knownMoney(c.analysisEstimatedUsd)} over ${plural(c.analysisAttempts, "recorded attempt")}${unpriced}`,
|
|
258
|
+
...(c.analysisHistoryUncertainRuns > 0
|
|
259
|
+
? [
|
|
260
|
+
`analysis history: ${plural(c.analysisHistoryUncertainRuns, "run")} missing or uncertain; --json lists each run`,
|
|
261
|
+
]
|
|
262
|
+
: []),
|
|
263
|
+
...(t.participants.total > 0
|
|
264
|
+
? [
|
|
265
|
+
`participants: ${t.participants.reachedGoal} of ${t.participants.total} reached the goal, ${t.participants.reportedFriction} reported friction`,
|
|
266
|
+
]
|
|
267
|
+
: []),
|
|
268
|
+
...(verdicts.length > 0 ? [`verdicts: ${verdicts.join(", ")}`] : []),
|
|
269
|
+
];
|
|
270
|
+
}
|
|
271
|
+
function dayLine(row) {
|
|
272
|
+
return `- ${row.day}: ${plural(row.runs, "run")}, ${row.live} live, known study spend ${knownMoney(row.costs.estimatedTotalUsd)}${unpricedTail(row.unpricedRuns, row.costs.analysisUnpricedAttempts)}`;
|
|
273
|
+
}
|
|
274
|
+
/** "; 2 unpriced runs, 1 unpriced analysis", or nothing when both are zero. */
|
|
275
|
+
function unpricedTail(runs, analyses) {
|
|
276
|
+
if (runs === 0 && analyses === 0)
|
|
277
|
+
return "";
|
|
278
|
+
return `; ${plural(runs, "unpriced run")}, ${plural(analyses, "unpriced analysis", "unpriced analyses")}`;
|
|
279
|
+
}
|
|
215
280
|
export function formatStatsHuman(result) {
|
|
216
281
|
if (!result.ok)
|
|
217
|
-
return
|
|
282
|
+
return { error: result.error };
|
|
218
283
|
const t = result.totals;
|
|
219
284
|
const scope = [
|
|
220
|
-
result.
|
|
285
|
+
result.study === undefined ? undefined : `lab ${result.study}`,
|
|
221
286
|
result.since === undefined ? undefined : `since ${result.since}`,
|
|
222
287
|
].filter((part) => part !== undefined);
|
|
223
288
|
const lines = [
|
|
224
289
|
`humanish stats${scope.length === 0 ? "" : ` (${scope.join(", ")})`}`,
|
|
225
|
-
|
|
226
|
-
`known estimated spend: ${knownMoney(t.costs.estimatedTotalUsd)}`,
|
|
227
|
-
`participants + desktops: ${knownMoney(t.costs.runEstimatedUsd)}; ${t.costs.incompleteRunEstimates} run(s) with incomplete accounting`,
|
|
228
|
-
`analysis: ${knownMoney(t.costs.analysisEstimatedUsd)} over ${t.costs.analysisAttempts} recorded attempt(s); ${t.costs.analysisUnpricedAttempts} unpriced, ${t.costs.analysisUnresolvedAttempts} unresolved`,
|
|
229
|
-
`analysis history: ${t.costs.analysisHistoryUncertainRuns} run(s) missing or uncertain; use --json for per-run accounting`,
|
|
230
|
-
`participants: ${t.participants.reachedGoal}/${t.participants.total} recorded goal completions, ${t.participants.reportedFriction} reported friction`,
|
|
231
|
-
`verdicts: ${Object.entries(t.verdicts)
|
|
232
|
-
.map(([verdict, count]) => `${verdict} ${count}`)
|
|
233
|
-
.join(", ") || "none recorded"}`,
|
|
290
|
+
...runCountLines(t),
|
|
234
291
|
];
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
292
|
+
// Free dry runs alone have no spend, outcome or duration to report. Anything else, an unreadable
|
|
293
|
+
// directory or a dry run that records a cost included, gets the full report.
|
|
294
|
+
const reportable = t.runs > 0 && !onlyFreeDryRuns(t);
|
|
295
|
+
if (reportable) {
|
|
296
|
+
lines.push(...totalsLines(t));
|
|
297
|
+
if (result.studies.length > 0)
|
|
298
|
+
lines.push("", "per lab:", ...result.studies.map((row) => {
|
|
299
|
+
const rate = row.passRate === undefined ? "no verdicts" : `${row.passed} of ${row.judged} passed`;
|
|
300
|
+
const duration = row.medianDurationMs === undefined
|
|
301
|
+
? "no timed live runs"
|
|
302
|
+
: `median ${minutes(row.medianDurationMs)} over ${row.durationSamples}`;
|
|
303
|
+
const cost = row.medianCostUsd === undefined
|
|
304
|
+
? "no priced participant/desktop runs"
|
|
305
|
+
: `participant/desktop median ${money(row.medianCostUsd)} over ${row.costSamples}`;
|
|
306
|
+
return `- ${row.study}: ${plural(row.runs, "run")}, ${row.live} live; ${rate}; ${duration}; known study spend ${knownMoney(row.costs.estimatedTotalUsd)}; ${cost}${unpricedTail(row.unpricedRuns, row.costs.analysisUnpricedAttempts)}`;
|
|
307
|
+
}));
|
|
308
|
+
if (result.days.length > 0)
|
|
309
|
+
lines.push("", "by day:", ...result.days.map(dayLine));
|
|
253
310
|
}
|
|
254
311
|
if (result.unreadable.length > 0)
|
|
255
312
|
lines.push("", `unreadable run directories: ${result.unreadable.join(", ")}`);
|
|
256
|
-
|
|
313
|
+
if (reportable)
|
|
314
|
+
lines.push("", result.note);
|
|
257
315
|
return `${lines.join("\n")}\n`;
|
|
258
316
|
}
|
package/dist/run/status.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RunBundle } from "./bundle.js";
|
|
2
|
+
import { type RunStudyProvenance } from "./study-provenance.js";
|
|
2
3
|
import { type PreparedOutputRoot } from "./contained-output.js";
|
|
3
4
|
import type { ExecutionOutcome } from "./judge.js";
|
|
4
5
|
export declare const RUN_STATUS_SCHEMA = "humanish.run-status.v1";
|
|
@@ -12,15 +13,6 @@ export declare const RUN_STATUS_TOUCH_MS = 5000;
|
|
|
12
13
|
* slack so an ordinary scheduling hiccup or a slow disk never mislabels a healthy run.
|
|
13
14
|
*/
|
|
14
15
|
export declare const RUN_STATUS_STALE_MS: number;
|
|
15
|
-
/** Which manifest a run came from, when it came from one. */
|
|
16
|
-
export interface RunLabProvenance {
|
|
17
|
-
/** The lab id as declared in its manifest (`config.id`). */
|
|
18
|
-
id: string;
|
|
19
|
-
/** Repo-relative manifest path, when the run came from a file on disk. */
|
|
20
|
-
path?: string;
|
|
21
|
-
/** `committed` = humanish/labs, `ignored` = a local overlay, `explicit` = a path the operator passed. */
|
|
22
|
-
origin?: "committed" | "ignored" | "explicit";
|
|
23
|
-
}
|
|
24
16
|
type RunStatusState = "running" | "finished" | "interrupted";
|
|
25
17
|
/** The signals the CLI's run handler records when it stops a run. */
|
|
26
18
|
export type RunInterruptSignal = "SIGINT" | "SIGTERM" | "SIGHUP";
|
|
@@ -49,8 +41,10 @@ export interface RunStatusRecord {
|
|
|
49
41
|
runId: string;
|
|
50
42
|
state: RunStatusState;
|
|
51
43
|
mode: "dry-run" | "live";
|
|
52
|
-
/** Absent when the run did not come from a
|
|
53
|
-
|
|
44
|
+
/** Absent when the run did not come from a study file (a library caller, a bare `run`). */
|
|
45
|
+
study?: RunStudyProvenance;
|
|
46
|
+
/** `study`'s value, written beside it until 0.109. Read either through studyProvenanceOf. */
|
|
47
|
+
lab?: RunStudyProvenance;
|
|
54
48
|
/** The pid that owns the run, for local liveness checks. */
|
|
55
49
|
pid: number;
|
|
56
50
|
startedAt: string;
|
|
@@ -68,7 +62,7 @@ export interface RunStatusHandle {
|
|
|
68
62
|
* still has a record to classify. */
|
|
69
63
|
readonly started: Promise<void>;
|
|
70
64
|
/** Finalize: state `finished`, `completedAt`, and the derived outcome. Stops the cadence.
|
|
71
|
-
* Idempotent
|
|
65
|
+
* Idempotent: a second call is a no-op, so a route with several exit paths is safe. */
|
|
72
66
|
finish(outcome?: RunStatusOutcome): Promise<void>;
|
|
73
67
|
/** After finish, add the result's ok and execution outcome to the finished record, so status.json
|
|
74
68
|
* and the result agree. Before finish it does nothing. */
|
|
@@ -85,12 +79,12 @@ export interface RunStatusHandle {
|
|
|
85
79
|
export interface BeginRunStatusOptions {
|
|
86
80
|
runId: string;
|
|
87
81
|
mode: "dry-run" | "live";
|
|
88
|
-
lab?:
|
|
82
|
+
lab?: RunStudyProvenance | undefined;
|
|
89
83
|
}
|
|
90
84
|
/**
|
|
91
85
|
* Start a run's status record and keep it fresh. Fire-and-forget by design: a status write that
|
|
92
86
|
* fails must never fail the run it describes, so every write swallows its error. The interval is
|
|
93
|
-
* `unref`'d
|
|
87
|
+
* `unref`'d, so this file can never be the reason a process stays alive.
|
|
94
88
|
*/
|
|
95
89
|
export declare function beginRunStatus(runPaths: PreparedOutputRoot, options: BeginRunStatusOptions): RunStatusHandle;
|
|
96
90
|
/** The three ways a run reads from disk. `interrupted` is a record its stopped process wrote, or a
|
|
@@ -103,19 +97,4 @@ export type RunLiveness = "running" | "interrupted" | "finished";
|
|
|
103
97
|
export declare function classifyRunStatus(record: Pick<RunStatusRecord, "state" | "updatedAt">, nowMs: number, staleMs?: number): RunLiveness;
|
|
104
98
|
/** Shape guard for a record read off disk. Unknown extra fields are tolerated (additive contract). */
|
|
105
99
|
export declare function isRunStatusRecord(value: unknown): value is RunStatusRecord;
|
|
106
|
-
/**
|
|
107
|
-
* The legacy bridge: infer a lab id for a bundle written before this contract, where the only
|
|
108
|
-
* attribution was the `lab:<id>` convention on persona/scenario source strings. Deliberately
|
|
109
|
-
* conservative — it reads the convention and nothing else, and a `lab:` prefix with an empty
|
|
110
|
-
* remainder is not an id. Ids may contain colons (the removed meta-lab wrote `oss:meta`), so
|
|
111
|
-
* only the first segment is stripped. Returns undefined when the bundle carries no such marker.
|
|
112
|
-
*/
|
|
113
|
-
export declare function inferLegacyLabId(bundle: {
|
|
114
|
-
persona?: {
|
|
115
|
-
source?: string;
|
|
116
|
-
};
|
|
117
|
-
scenario?: {
|
|
118
|
-
source?: string;
|
|
119
|
-
};
|
|
120
|
-
}): string | undefined;
|
|
121
100
|
export {};
|
package/dist/run/status.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// Public safety: it holds only the run id, the lab id/path/origin (the strings `humanish lab list`
|
|
10
10
|
// prints), the mode, a local pid and timestamps. It holds no hostname or user/path identity: an
|
|
11
11
|
// operator may share the run directory, so a share-safety gate must have nothing to strip here.
|
|
12
|
+
import { isProvenanceField, studyFields } from "./study-provenance.js";
|
|
12
13
|
import { writeContainedOutputFile } from "./contained-output.js";
|
|
13
14
|
import { redactText } from "../evidence/redaction.js";
|
|
14
15
|
export const RUN_STATUS_SCHEMA = "humanish.run-status.v1";
|
|
@@ -46,7 +47,7 @@ export function runStatusOutcome(bundle) {
|
|
|
46
47
|
/**
|
|
47
48
|
* Start a run's status record and keep it fresh. Fire-and-forget by design: a status write that
|
|
48
49
|
* fails must never fail the run it describes, so every write swallows its error. The interval is
|
|
49
|
-
* `unref`'d
|
|
50
|
+
* `unref`'d, so this file can never be the reason a process stays alive.
|
|
50
51
|
*/
|
|
51
52
|
export function beginRunStatus(runPaths, options) {
|
|
52
53
|
const iso = () => new Date().toISOString();
|
|
@@ -56,7 +57,7 @@ export function beginRunStatus(runPaths, options) {
|
|
|
56
57
|
runId: options.runId,
|
|
57
58
|
state: "running",
|
|
58
59
|
mode: options.mode,
|
|
59
|
-
...(options.lab
|
|
60
|
+
...studyFields(options.lab),
|
|
60
61
|
pid: process.pid,
|
|
61
62
|
startedAt,
|
|
62
63
|
updatedAt: startedAt,
|
|
@@ -170,30 +171,7 @@ export function isRunStatusRecord(value) {
|
|
|
170
171
|
return false;
|
|
171
172
|
if (typeof record.startedAt !== "string" || typeof record.updatedAt !== "string")
|
|
172
173
|
return false;
|
|
173
|
-
if (record.
|
|
174
|
-
|
|
175
|
-
return false;
|
|
176
|
-
if (typeof record.lab.id !== "string")
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
174
|
+
if (!isProvenanceField(record.study) || !isProvenanceField(record.lab))
|
|
175
|
+
return false;
|
|
179
176
|
return true;
|
|
180
177
|
}
|
|
181
|
-
/**
|
|
182
|
-
* The legacy bridge: infer a lab id for a bundle written before this contract, where the only
|
|
183
|
-
* attribution was the `lab:<id>` convention on persona/scenario source strings. Deliberately
|
|
184
|
-
* conservative — it reads the convention and nothing else, and a `lab:` prefix with an empty
|
|
185
|
-
* remainder is not an id. Ids may contain colons (the removed meta-lab wrote `oss:meta`), so
|
|
186
|
-
* only the first segment is stripped. Returns undefined when the bundle carries no such marker.
|
|
187
|
-
*/
|
|
188
|
-
export function inferLegacyLabId(bundle) {
|
|
189
|
-
for (const source of [bundle.persona?.source, bundle.scenario?.source]) {
|
|
190
|
-
if (typeof source !== "string")
|
|
191
|
-
continue;
|
|
192
|
-
if (!source.startsWith("lab:"))
|
|
193
|
-
continue;
|
|
194
|
-
const id = source.slice("lab:".length).trim();
|
|
195
|
-
if (id !== "")
|
|
196
|
-
return id;
|
|
197
|
-
}
|
|
198
|
-
return undefined;
|
|
199
|
-
}
|
package/dist/run/stored-runs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { lstat, readdir } from "node:fs/promises";
|
|
2
|
+
import { runNotFoundMessage } from "./run-not-found.js";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { redactText } from "../evidence/redaction.js";
|
|
4
5
|
import { bindExistingRunArtifactPaths, RUNS_RELATIVE_ROOT, isSafeRunIdSegment, resolveRunsRoot, validatePreparedRunArtifactPaths, } from "./paths.js";
|
|
@@ -66,7 +67,7 @@ export async function cleanupRun(cwdInput, runInput, hooks = {}) {
|
|
|
66
67
|
if (!resolved) {
|
|
67
68
|
return cleanupRefusal(cwd, runInput, checkedAt, {
|
|
68
69
|
code: "HUMANISH_RUN_NOT_FOUND",
|
|
69
|
-
message:
|
|
70
|
+
message: await runNotFoundMessage(cwd, runInput),
|
|
70
71
|
});
|
|
71
72
|
}
|
|
72
73
|
const runPaths = resolved;
|
package/dist/run/stream-shape.js
CHANGED
|
@@ -140,7 +140,7 @@ export function isRunSimulationStatus(value) {
|
|
|
140
140
|
value === "running" ||
|
|
141
141
|
value === "passed" ||
|
|
142
142
|
// Participant outcomes (docs/principles/three-roles.md). This runtime allowlist is the actual
|
|
143
|
-
// gate
|
|
143
|
+
// gate; the TS union alone does not validate a bundle read back from disk.
|
|
144
144
|
value === "abandoned" ||
|
|
145
145
|
value === "incomplete" ||
|
|
146
146
|
value === "complete" ||
|
package/dist/run/streams.d.ts
CHANGED
|
@@ -70,8 +70,8 @@ export interface RunDesktopGeometry {
|
|
|
70
70
|
* Without this, a floored run is indistinguishable from a faithful one: `verified` compares
|
|
71
71
|
* the floored number with itself and reports a match, so a reader of the bundle sees
|
|
72
72
|
* requested 500 / verified 500 and reasonably concludes a 500-wide preset was asked for. A
|
|
73
|
-
* `mobile` (414) and a `small-mobile` (360)
|
|
74
|
-
* When this field is set, the preset width did not render
|
|
73
|
+
* `mobile` (414) and a `small-mobile` (360) participant both render at 500 and look identical
|
|
74
|
+
* here. When this field is set, the preset width did not render.
|
|
75
75
|
*/
|
|
76
76
|
declared?: {
|
|
77
77
|
width: number;
|
|
@@ -96,7 +96,7 @@ export interface RunDesktopGeometry {
|
|
|
96
96
|
source: "cdp";
|
|
97
97
|
};
|
|
98
98
|
/**
|
|
99
|
-
* Mobile fidelity beyond viewport size
|
|
99
|
+
* Mobile fidelity beyond viewport size, present only when the lab asked for it. `requested`
|
|
100
100
|
* is what was applied through CDP; `resolved` is what the page reported about itself afterwards
|
|
101
101
|
* and is the proof, never copied from the request. A run without this block is a
|
|
102
102
|
* responsive-viewport study, whatever its preset is named.
|
|
@@ -122,7 +122,7 @@ export interface RunDesktopGeometry {
|
|
|
122
122
|
};
|
|
123
123
|
/**
|
|
124
124
|
* Page targets the participant drove after the launch page (a link that opened in a new tab)
|
|
125
|
-
* whose own read-back reported the requested viewport width
|
|
125
|
+
* whose own read-back reported the requested viewport width. Absent when the
|
|
126
126
|
* participant never left the launch tab; a later tab that did not report the width is a
|
|
127
127
|
* participant warning instead.
|
|
128
128
|
*/
|
|
@@ -234,9 +234,9 @@ export interface RunStream {
|
|
|
234
234
|
};
|
|
235
235
|
actor?: ActorTrace;
|
|
236
236
|
/**
|
|
237
|
-
* Mid-run partial actor evidence
|
|
237
|
+
* Mid-run partial actor evidence: the redacted trace items recorded so far,
|
|
238
238
|
* flushed while a live participant is still running so the attached Observer's timeline can
|
|
239
|
-
* grow. It is deliberately not an ActorTrace: a running participant has no
|
|
239
|
+
* grow. It is deliberately not an ActorTrace: a running participant has no final status,
|
|
240
240
|
* completionReason, or completedAt, and this shape cannot claim them. Present only on
|
|
241
241
|
* `inProgress` bundles; the final write replaces it with the real `actor` and never
|
|
242
242
|
* carries it.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Which study a run came from, when it came from one. */
|
|
2
|
+
export interface RunStudyProvenance {
|
|
3
|
+
/** The study id its file declares (`config.id`). */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Project-relative path of the study file, when the run came from a file on disk. */
|
|
6
|
+
path?: string;
|
|
7
|
+
/**
|
|
8
|
+
* `committed` = humanish/studies or humanish/labs, `ignored` = a local overlay, `explicit` = a
|
|
9
|
+
* path the operator passed.
|
|
10
|
+
*/
|
|
11
|
+
origin?: "committed" | "ignored" | "explicit";
|
|
12
|
+
}
|
|
13
|
+
/** Whether a saved record's `study` or `lab` field is absent or shaped like a provenance. */
|
|
14
|
+
export declare function isProvenanceField(value: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* A saved record's study: a valid `study`, else a valid `lab`, else the id its persona or scenario
|
|
17
|
+
* source names by convention.
|
|
18
|
+
*/
|
|
19
|
+
export declare function studyProvenanceOf(record: {
|
|
20
|
+
study?: unknown;
|
|
21
|
+
lab?: unknown;
|
|
22
|
+
persona?: {
|
|
23
|
+
source?: unknown;
|
|
24
|
+
};
|
|
25
|
+
scenario?: {
|
|
26
|
+
source?: unknown;
|
|
27
|
+
};
|
|
28
|
+
}): RunStudyProvenance | undefined;
|
|
29
|
+
/** `study` and `lab` with the same value, as run.json and status.json write them until 0.109. */
|
|
30
|
+
export declare function studyFields(study: RunStudyProvenance | undefined): {
|
|
31
|
+
study?: RunStudyProvenance;
|
|
32
|
+
lab?: RunStudyProvenance;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The study id a run names by the `study:<id>` or `lab:<id>` convention on its persona or scenario
|
|
36
|
+
* source, the only attribution a run written before `lab` and `study` has. A prefix with an empty
|
|
37
|
+
* remainder is not an id. Ids may contain colons (`lab:oss:meta`), so only the prefix is stripped.
|
|
38
|
+
* Readers keep both prefixes for good: saved runs say `lab:`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function inferLegacyStudyId(bundle: {
|
|
41
|
+
persona?: {
|
|
42
|
+
source?: unknown;
|
|
43
|
+
};
|
|
44
|
+
scenario?: {
|
|
45
|
+
source?: unknown;
|
|
46
|
+
};
|
|
47
|
+
}): string | undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Which study a saved run came from. run.json and status.json write it as `study`, and as `lab`
|
|
2
|
+
// with the same value until 0.109 drops `lab`. Every reader goes through
|
|
3
|
+
// studyProvenanceOf, which also reads a run older than both fields by the `study:<id>` or
|
|
4
|
+
// `lab:<id>` convention on its persona and scenario sources.
|
|
5
|
+
const ORIGINS = ["committed", "ignored", "explicit"];
|
|
6
|
+
/** `value` as a provenance when it has an id, keeping only its fields that are valid. */
|
|
7
|
+
function provenance(value) {
|
|
8
|
+
if (value === null || typeof value !== "object")
|
|
9
|
+
return undefined;
|
|
10
|
+
const record = value;
|
|
11
|
+
if (typeof record.id !== "string" || record.id === "")
|
|
12
|
+
return undefined;
|
|
13
|
+
const origin = record.origin;
|
|
14
|
+
return {
|
|
15
|
+
id: record.id,
|
|
16
|
+
...(typeof record.path === "string" ? { path: record.path } : {}),
|
|
17
|
+
...(typeof origin === "string" && ORIGINS.includes(origin)
|
|
18
|
+
? { origin: origin }
|
|
19
|
+
: {}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Whether a saved record's `study` or `lab` field is absent or shaped like a provenance. */
|
|
23
|
+
export function isProvenanceField(value) {
|
|
24
|
+
if (value === undefined)
|
|
25
|
+
return true;
|
|
26
|
+
if (value === null || typeof value !== "object")
|
|
27
|
+
return false;
|
|
28
|
+
return typeof value.id === "string";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A saved record's study: a valid `study`, else a valid `lab`, else the id its persona or scenario
|
|
32
|
+
* source names by convention.
|
|
33
|
+
*/
|
|
34
|
+
export function studyProvenanceOf(record) {
|
|
35
|
+
const declared = provenance(record.study) ?? provenance(record.lab);
|
|
36
|
+
if (declared !== undefined)
|
|
37
|
+
return declared;
|
|
38
|
+
const id = inferLegacyStudyId(record);
|
|
39
|
+
return id === undefined ? undefined : { id };
|
|
40
|
+
}
|
|
41
|
+
/** `study` and `lab` with the same value, as run.json and status.json write them until 0.109. */
|
|
42
|
+
export function studyFields(study) {
|
|
43
|
+
return study === undefined ? {} : { study, lab: study };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The study id a run names by the `study:<id>` or `lab:<id>` convention on its persona or scenario
|
|
47
|
+
* source, the only attribution a run written before `lab` and `study` has. A prefix with an empty
|
|
48
|
+
* remainder is not an id. Ids may contain colons (`lab:oss:meta`), so only the prefix is stripped.
|
|
49
|
+
* Readers keep both prefixes for good: saved runs say `lab:`.
|
|
50
|
+
*/
|
|
51
|
+
export function inferLegacyStudyId(bundle) {
|
|
52
|
+
for (const source of [bundle.persona?.source, bundle.scenario?.source]) {
|
|
53
|
+
if (typeof source !== "string")
|
|
54
|
+
continue;
|
|
55
|
+
const prefix = ["study:", "lab:"].find((candidate) => source.startsWith(candidate));
|
|
56
|
+
if (prefix === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
const id = source.slice(prefix.length).trim();
|
|
59
|
+
if (id !== "")
|
|
60
|
+
return id;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** The schema of a study's result on every route. */
|
|
2
|
+
export declare const STUDY_RESULT_SCHEMA = "humanish.study-result.v1";
|
|
3
|
+
/** The fields every route's result carries to name its route and its study. */
|
|
4
|
+
export interface StudyResultIdentity<R extends string> {
|
|
5
|
+
schema: typeof STUDY_RESULT_SCHEMA;
|
|
6
|
+
route: R;
|
|
7
|
+
/** The study's `id`. */
|
|
8
|
+
studyId: string;
|
|
9
|
+
/**
|
|
10
|
+
* The study's `id`, the same value as `studyId`.
|
|
11
|
+
* @deprecated Read `studyId`. The next minor removes it.
|
|
12
|
+
*/
|
|
13
|
+
labId: string;
|
|
14
|
+
}
|
|
15
|
+
/** The identity fields for a result of route `route` from the study `studyId`. */
|
|
16
|
+
export declare function studyResultIdentity<R extends string>(route: R, studyId: string): StudyResultIdentity<R>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The schema every route's result carries when a study runs: preview, computer use, scripted,
|
|
2
|
+
// terminal and shared world. `route` says which, and route-specific fields stay on their route's
|
|
3
|
+
// result type.
|
|
4
|
+
/** The schema of a study's result on every route. */
|
|
5
|
+
export const STUDY_RESULT_SCHEMA = "humanish.study-result.v1";
|
|
6
|
+
/** The identity fields for a result of route `route` from the study `studyId`. */
|
|
7
|
+
export function studyResultIdentity(route, studyId) {
|
|
8
|
+
return { schema: STUDY_RESULT_SCHEMA, route, studyId, labId: studyId };
|
|
9
|
+
}
|
package/dist/run/text.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
/** Escape a literal string for use inside a RegExp source. */
|
|
2
2
|
export declare function escapeRegExp(value: string): string;
|
|
3
|
+
/** "1 run", "2 runs"; `plural` names the irregular form, as in plural(n, "analysis", "analyses"). */
|
|
4
|
+
export declare function plural(count: number, singular: string, pluralForm?: string): string;
|
package/dist/run/text.js
CHANGED
|
@@ -2,3 +2,7 @@
|
|
|
2
2
|
export function escapeRegExp(value) {
|
|
3
3
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4
4
|
}
|
|
5
|
+
/** "1 run", "2 runs"; `plural` names the irregular form, as in plural(n, "analysis", "analyses"). */
|
|
6
|
+
export function plural(count, singular, pluralForm = `${singular}s`) {
|
|
7
|
+
return `${count} ${count === 1 ? singular : pluralForm}`;
|
|
8
|
+
}
|