humanish 0.107.0 → 0.109.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +73 -69
- package/CHANGELOG.md +27 -0
- package/CONTEXT.md +51 -44
- package/README.md +148 -175
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-trace.js +2 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +20 -18
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +3 -3
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +18 -18
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/admission-limit.d.ts +3 -3
- package/dist/actors/computer-use/admission-limit.js +4 -4
- package/dist/actors/computer-use/executor-error.d.ts +2 -2
- package/dist/actors/computer-use/executor-error.js +3 -3
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +15 -15
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/debrief.js +2 -2
- package/dist/actors/computer-use/loop/ending.d.ts +6 -6
- package/dist/actors/computer-use/loop/ending.js +18 -17
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +15 -14
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +12 -12
- package/dist/actors/computer-use/loop/session.d.ts +4 -4
- package/dist/actors/computer-use/loop/session.js +4 -4
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +11 -9
- package/dist/actors/computer-use/loop/types.d.ts +47 -45
- package/dist/actors/computer-use/loop/usage.d.ts +2 -2
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/loop.d.ts +6 -1
- package/dist/actors/computer-use/loop.js +26 -4
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +13 -10
- package/dist/actors/computer-use/openai-provider.js +52 -41
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/computer-use/provider-error.d.ts +4 -4
- package/dist/actors/computer-use/provider-error.js +6 -6
- package/dist/actors/contract.d.ts +82 -47
- package/dist/actors/contract.js +30 -24
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +13 -12
- package/dist/actors/local-agent/cli.d.ts +9 -7
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +8 -8
- package/dist/actors/registry.d.ts +12 -12
- package/dist/actors/registry.js +21 -20
- package/dist/actors/scripted-browser/actor.d.ts +10 -10
- package/dist/actors/scripted-browser/actor.js +17 -17
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/automatic-completion.d.ts +7 -7
- package/dist/analysis/automatic-completion.js +1 -1
- package/dist/analysis/automatic-config.d.ts +6 -6
- package/dist/analysis/automatic-config.js +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/execute.d.ts +1 -1
- package/dist/analysis/execute.js +1 -1
- package/dist/analysis/service.js +5 -5
- package/dist/analysis/types.d.ts +6 -0
- package/dist/browser-control/client.js +16 -16
- package/dist/browser-control/dispatcher.js +4 -4
- package/dist/browser-control/protocol.js +14 -14
- package/dist/browser-control/recording-transfer.js +4 -4
- package/dist/browser-control/transport.js +7 -7
- package/dist/cli/commands/analysis-signals.d.ts +2 -2
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +48 -35
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.d.ts +0 -1
- package/dist/cli/commands/observe.js +136 -112
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +136 -139
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +27 -24
- package/dist/cli/commands/study-format.d.ts +9 -0
- package/dist/cli/commands/{lab-format.js → study-format.js} +39 -27
- package/dist/cli/commands/{lab-route-computer-use.d.ts → study-route-computer-use.d.ts} +6 -6
- package/dist/cli/commands/{lab-route-computer-use.js → study-route-computer-use.js} +17 -18
- package/dist/cli/commands/{lab-route-open.d.ts → study-route-open.d.ts} +4 -4
- package/dist/cli/commands/{lab-route-open.js → study-route-open.js} +2 -2
- package/dist/cli/commands/{lab-route-preview.d.ts → study-route-preview.d.ts} +7 -7
- package/dist/cli/commands/{lab-route-preview.js → study-route-preview.js} +7 -6
- package/dist/cli/commands/study-route-run.d.ts +19 -0
- package/dist/cli/commands/{lab-route-run.js → study-route-run.js} +6 -6
- package/dist/cli/commands/study-route-scripted.d.ts +17 -0
- package/dist/cli/commands/{lab-route-scripted.js → study-route-scripted.js} +4 -4
- package/dist/cli/commands/{lab-route-shared-world.d.ts → study-route-shared-world.d.ts} +5 -5
- package/dist/cli/commands/{lab-route-shared-world.js → study-route-shared-world.js} +10 -10
- package/dist/cli/commands/study-route-terminal.d.ts +17 -0
- package/dist/cli/commands/{lab-route-terminal.js → study-route-terminal.js} +4 -4
- package/dist/cli/commands/study-run.d.ts +9 -0
- package/dist/cli/commands/{lab-run.js → study-run.js} +44 -45
- package/dist/cli/commands/{lab-scorer.d.ts → study-scorer.d.ts} +7 -7
- package/dist/cli/commands/{lab-scorer.js → study-scorer.js} +2 -2
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +146 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +31 -31
- package/dist/cli/commands/watch.js +71 -121
- package/dist/cli/deprecations.d.ts +6 -0
- package/dist/cli/deprecations.js +18 -0
- package/dist/cli/doctor.d.ts +18 -8
- package/dist/cli/doctor.js +114 -59
- package/dist/cli/first-run-path.d.ts +15 -13
- package/dist/cli/first-run-path.js +35 -33
- package/dist/cli/io.d.ts +44 -9
- package/dist/cli/io.js +98 -23
- package/dist/cli/observer-follow.d.ts +3 -3
- package/dist/cli/observer-follow.js +6 -7
- package/dist/cli/orientation.d.ts +10 -7
- package/dist/cli/orientation.js +89 -47
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +111 -43
- package/dist/cli/telemetry.d.ts +16 -16
- package/dist/cli/telemetry.js +46 -44
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +17 -17
- package/dist/comms/connections.d.ts +1 -1
- package/dist/comms/connections.js +2 -2
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.d.ts +5 -5
- package/dist/comms/external-evidence.js +5 -4
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +3 -3
- package/dist/comms/fake-inbox.js +3 -3
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/receiving-runtime.d.ts +4 -4
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +38 -39
- package/dist/comms/sandbox-catch.js +36 -37
- package/dist/comms/setup.d.ts +2 -2
- package/dist/comms/setup.js +56 -25
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +38 -80
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +10 -10
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/feedback/proof.d.ts +1 -1
- package/dist/feedback/proof.js +2 -2
- package/dist/guest/bootstrap.js +6 -6
- package/dist/guest/browser-tools.js +8 -8
- package/dist/guest/chromium-text.js +19 -19
- package/dist/guest/desktop-executor.d.ts +2 -2
- package/dist/guest/desktop-executor.js +20 -20
- package/dist/guest/desktop-keys.js +4 -4
- package/dist/guest/desktop-media.d.ts +2 -2
- package/dist/guest/desktop-media.js +16 -16
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/desktop-native.js +10 -10
- package/dist/guest/runtime-desktop.js +2 -2
- package/dist/guest/runtime-processes.d.ts +2 -2
- package/dist/guest/runtime-processes.js +2 -2
- package/dist/guest/runtime.js +6 -6
- package/dist/index.d.ts +14 -14
- package/dist/index.js +8 -8
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/observer/artifact.d.ts +2 -2
- package/dist/observer/artifact.js +7 -7
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +3 -1
- package/dist/observer/library.js +8 -3
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +17 -6
- package/dist/observer/run-routes.d.ts +4 -3
- package/dist/observer/run-routes.js +38 -13
- package/dist/observer/serve.d.ts +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +18 -17
- package/dist/routes/computer-use/bundle.d.ts +2 -2
- package/dist/routes/computer-use/bundle.js +10 -9
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +6 -6
- package/dist/routes/computer-use/e2b-desktop/comms.js +18 -17
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/prepare.js +10 -10
- package/dist/routes/computer-use/e2b-desktop/start.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/teardown.js +2 -2
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +27 -26
- package/dist/routes/computer-use/fanout-records.js +12 -13
- package/dist/routes/computer-use/live-flush.d.ts +4 -4
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +5 -4
- package/dist/routes/computer-use/live-phase.js +8 -8
- package/dist/routes/computer-use/local-tree-pack.d.ts +5 -5
- package/dist/routes/computer-use/local-tree-pack.js +1 -1
- package/dist/routes/computer-use/local-vm.d.ts +8 -8
- package/dist/routes/computer-use/local-vm.js +3 -3
- package/dist/routes/computer-use/participant-desktop.d.ts +7 -7
- package/dist/routes/computer-use/participant-desktop.js +5 -5
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +10 -10
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +33 -15
- package/dist/routes/computer-use/participant-prompt.d.ts +15 -15
- package/dist/routes/computer-use/participant-prompt.js +9 -9
- package/dist/routes/computer-use/participant-runs.d.ts +16 -16
- package/dist/routes/computer-use/participant-runs.js +26 -25
- package/dist/routes/computer-use/plan.d.ts +12 -12
- package/dist/routes/computer-use/plan.js +42 -42
- package/dist/routes/computer-use/preflight.d.ts +5 -5
- package/dist/routes/computer-use/preflight.js +25 -25
- package/dist/routes/computer-use/rerun-selection.d.ts +1 -1
- package/dist/routes/computer-use/rerun-selection.js +4 -3
- package/dist/routes/computer-use/result.d.ts +4 -4
- package/dist/routes/computer-use/result.js +22 -21
- package/dist/routes/computer-use/route.d.ts +12 -11
- package/dist/routes/computer-use/route.js +31 -30
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +32 -32
- package/dist/routes/computer-use/setup.d.ts +23 -23
- package/dist/routes/computer-use/setup.js +28 -29
- package/dist/routes/computer-use/single-bundle.d.ts +11 -11
- package/dist/routes/computer-use/single-bundle.js +40 -41
- package/dist/routes/computer-use/subject-projection.d.ts +4 -4
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +71 -73
- package/dist/routes/computer-use/types.js +12 -12
- package/dist/routes/preview.d.ts +13 -7
- package/dist/routes/preview.js +11 -7
- package/dist/routes/scripted/bundle.d.ts +7 -7
- package/dist/routes/scripted/bundle.js +20 -18
- package/dist/routes/scripted/plan.d.ts +8 -8
- package/dist/routes/scripted/plan.js +13 -13
- package/dist/routes/scripted/result.d.ts +3 -3
- package/dist/routes/scripted/result.js +13 -13
- package/dist/routes/scripted/route.d.ts +9 -9
- package/dist/routes/scripted/route.js +15 -16
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +5 -5
- package/dist/routes/scripted/setup.d.ts +6 -6
- package/dist/routes/scripted/setup.js +8 -8
- package/dist/routes/scripted/subject.d.ts +5 -5
- package/dist/routes/scripted/subject.js +4 -4
- package/dist/routes/scripted/surface-records.d.ts +1 -1
- package/dist/routes/scripted/surface-records.js +4 -4
- package/dist/routes/scripted/surface-sessions.d.ts +3 -3
- package/dist/routes/scripted/types.d.ts +18 -20
- package/dist/routes/scripted/types.js +2 -2
- package/dist/routes/shared-world/bundle-records.js +11 -10
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +46 -43
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +2 -2
- package/dist/routes/shared-world/comms.d.ts +14 -14
- package/dist/routes/shared-world/comms.js +19 -18
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +10 -9
- package/dist/routes/shared-world/participant-specs.js +38 -31
- package/dist/routes/shared-world/plan.d.ts +9 -9
- package/dist/routes/shared-world/plan.js +16 -16
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.d.ts +8 -8
- package/dist/routes/shared-world/provisioned.js +18 -17
- package/dist/routes/shared-world/result.d.ts +6 -6
- package/dist/routes/shared-world/result.js +29 -29
- package/dist/routes/shared-world/route.d.ts +11 -11
- package/dist/routes/shared-world/route.js +40 -39
- package/dist/routes/shared-world/setup.d.ts +16 -16
- package/dist/routes/shared-world/setup.js +23 -23
- package/dist/routes/shared-world/types.d.ts +55 -53
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +5 -5
- package/dist/routes/terminal/adapter.js +9 -9
- package/dist/routes/terminal/bundle.d.ts +13 -13
- package/dist/routes/terminal/bundle.js +28 -27
- package/dist/routes/terminal/credentials.d.ts +8 -8
- package/dist/routes/terminal/credentials.js +12 -12
- package/dist/routes/terminal/dry-run.d.ts +4 -4
- package/dist/routes/terminal/dry-run.js +12 -12
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +5 -5
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/lifetime.d.ts +1 -1
- package/dist/routes/terminal/lifetime.js +1 -1
- package/dist/routes/terminal/live-finish.d.ts +2 -2
- package/dist/routes/terminal/live-finish.js +10 -10
- package/dist/routes/terminal/live-sandbox.d.ts +2 -2
- package/dist/routes/terminal/live-sandbox.js +15 -15
- package/dist/routes/terminal/participant-text.js +2 -1
- package/dist/routes/terminal/persona.d.ts +2 -2
- package/dist/routes/terminal/persona.js +3 -3
- package/dist/routes/terminal/plan.d.ts +7 -7
- package/dist/routes/terminal/plan.js +15 -15
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.d.ts +5 -5
- package/dist/routes/terminal/result.js +14 -14
- package/dist/routes/terminal/route.d.ts +9 -9
- package/dist/routes/terminal/route.js +19 -20
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.d.ts +5 -5
- package/dist/routes/terminal/session.js +14 -13
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +4 -4
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +48 -50
- package/dist/routes/terminal/types.js +5 -5
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +49 -49
- package/dist/run/bundle.js +3 -2
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.d.ts +23 -0
- package/dist/run/costs.js +79 -44
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.d.ts +1 -1
- package/dist/run/dry-run-inputs.js +2 -2
- package/dist/run/dry-run.js +20 -20
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/outcomes.d.ts +1 -1
- package/dist/run/participant.d.ts +1 -1
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/preflight-receipts.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +22 -15
- package/dist/run/projection.d.ts +46 -46
- package/dist/run/projection.js +57 -57
- package/dist/run/reclaim.d.ts +1 -1
- package/dist/run/reclaim.js +3 -3
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-cost.d.ts +53 -0
- package/dist/run/run-cost.js +105 -0
- package/dist/run/run-index-analysis.d.ts +15 -0
- package/dist/run/run-index-analysis.js +77 -0
- package/dist/run/run-index.d.ts +19 -7
- package/dist/run/run-index.js +77 -64
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +6 -5
- package/dist/run/run.js +3 -3
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +37 -36
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +7 -7
- package/dist/run/stats.d.ts +14 -8
- package/dist/run/stats.js +121 -63
- package/dist/run/status.d.ts +16 -29
- package/dist/run/status.js +10 -29
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +7 -7
- package/dist/run/study-provenance.d.ts +49 -0
- package/dist/run/study-provenance.js +66 -0
- package/dist/run/study-result.d.ts +11 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-study.d.ts +112 -0
- package/dist/{run-lab.js → run-study.js} +52 -47
- package/dist/{lab → study}/adapter-extension.d.ts +15 -27
- package/dist/{lab → study}/adapter-extension.js +10 -45
- package/dist/{lab → study}/adapter-scorer-loader.d.ts +17 -17
- package/dist/{lab → study}/adapter-scorer-loader.js +34 -34
- package/dist/study/composition-rules.d.ts +7 -0
- package/dist/{lab → study}/composition-rules.js +53 -53
- package/dist/study/config.d.ts +15 -0
- package/dist/{lab → study}/config.js +98 -41
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/{lab → study}/device-presets.d.ts +10 -10
- package/dist/{lab → study}/device-presets.js +11 -11
- package/dist/study/discover.d.ts +75 -0
- package/dist/{lab → study}/discover.js +134 -95
- package/dist/{lab → study}/doctor.d.ts +19 -12
- package/dist/{lab → study}/doctor.js +58 -20
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +44 -0
- package/dist/{lab → study}/init-templates.d.ts +2 -2
- package/dist/study/init-templates.js +421 -0
- package/dist/{lab → study}/init.d.ts +2 -2
- package/dist/{lab → study}/init.js +46 -11
- package/dist/study/keys.d.ts +4 -0
- package/dist/{lab → study}/keys.js +46 -12
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/{lab → study}/parse/actors.d.ts +5 -5
- package/dist/{lab → study}/parse/actors.js +14 -14
- package/dist/study/parse/comms.d.ts +12 -0
- package/dist/{lab → study}/parse/comms.js +5 -5
- package/dist/study/parse/execution.d.ts +19 -0
- package/dist/{lab → study}/parse/execution.js +13 -13
- package/dist/study/parse/study-v3.d.ts +21 -0
- package/dist/study/parse/study-v3.js +259 -0
- package/dist/study/parse/subject-state.d.ts +30 -0
- package/dist/{lab → study}/parse/subject-state.js +19 -19
- package/dist/{lab → study}/parse/subject.d.ts +3 -3
- package/dist/{lab → study}/parse/subject.js +34 -34
- package/dist/{lab → study}/parse/values.d.ts +3 -3
- package/dist/{lab → study}/parse/values.js +3 -3
- package/dist/{lab → study}/persona-resolve.d.ts +8 -8
- package/dist/{lab → study}/persona-resolve.js +6 -6
- package/dist/{lab → study}/plan-base.d.ts +7 -7
- package/dist/{lab → study}/plan-base.js +1 -1
- package/dist/{lab → study}/plan-participants.d.ts +12 -12
- package/dist/{lab → study}/plan-participants.js +4 -4
- package/dist/{lab → study}/plan-types.d.ts +31 -31
- package/dist/{lab → study}/plan-types.js +2 -2
- package/dist/study/plan.d.ts +13 -0
- package/dist/study/plan.js +101 -0
- package/dist/study/preflight-probes.d.ts +3 -0
- package/dist/{lab → study}/preflight-probes.js +20 -19
- package/dist/study/preflight-result.d.ts +8 -0
- package/dist/{lab → study}/preflight-result.js +5 -4
- package/dist/study/preflight.d.ts +94 -0
- package/dist/{lab → study}/preflight.js +12 -12
- package/dist/{lab → study}/requirements.d.ts +3 -3
- package/dist/{lab → study}/requirements.js +1 -1
- package/dist/study/route-inputs.d.ts +28 -0
- package/dist/{lab → study}/route-inputs.js +1 -1
- package/dist/{lab → study}/routing.d.ts +39 -33
- package/dist/{lab → study}/routing.js +60 -29
- package/dist/{lab/run-lab-events.d.ts → study/run-study-events.d.ts} +10 -13
- package/dist/{lab/run-lab-events.js → study/run-study-events.js} +3 -9
- package/dist/{lab/run-lab-homes.d.ts → study/run-study-homes.d.ts} +21 -18
- package/dist/{lab/run-lab-homes.js → study/run-study-homes.js} +1 -1
- package/dist/study/run-study-options.d.ts +28 -0
- package/dist/{lab/run-lab-options.js → study/run-study-options.js} +29 -25
- package/dist/{lab/lab-deps.d.ts → study/study-deps.d.ts} +8 -13
- package/dist/{lab/lab-deps.js → study/study-deps.js} +2 -2
- package/dist/{lab → study}/summary.d.ts +16 -15
- package/dist/{lab → study}/summary.js +21 -21
- package/dist/{lab → study}/tasks.d.ts +18 -18
- package/dist/{lab → study}/tasks.js +14 -14
- package/dist/{lab → study}/types.d.ts +202 -196
- package/dist/{lab → study}/types.js +3 -1
- package/dist/{lab → study}/validation.d.ts +27 -27
- package/dist/{lab → study}/validation.js +53 -51
- package/dist/study/warnings.d.ts +12 -0
- package/dist/{lab → study}/warnings.js +62 -34
- package/dist/subject/clone.d.ts +7 -7
- package/dist/subject/clone.js +2 -2
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.d.ts +2 -2
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +4 -4
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +9 -10
- package/dist/subject/serve.d.ts +5 -5
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +4 -4
- package/dist/subject/state.js +1 -1
- package/dist/subject/steps.d.ts +6 -6
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/desktop-session.js +2 -2
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +6 -6
- package/dist/substrates/e2b/desktop-browser.js +9 -9
- package/dist/substrates/e2b/desktop-cdp.d.ts +10 -10
- package/dist/substrates/e2b/desktop-cdp.js +9 -9
- package/dist/substrates/e2b/desktop-executor.d.ts +2 -2
- package/dist/substrates/e2b/desktop-executor.js +13 -13
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +8 -8
- package/dist/substrates/e2b/desktop-media.d.ts +4 -4
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/lifetime.js +1 -1
- package/dist/substrates/e2b/sandbox.d.ts +4 -4
- package/dist/substrates/e2b/sandbox.js +2 -2
- package/dist/substrates/e2b/sdk.d.ts +12 -12
- package/dist/substrates/e2b/sdk.js +7 -7
- package/dist/substrates/local/runtime-config.d.ts +4 -4
- package/dist/substrates/local/runtime-config.js +4 -4
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +23 -23
- package/dist/tui/contract.js +11 -11
- package/dist/tui/launch.d.ts +7 -7
- package/dist/tui/launch.js +36 -31
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +139 -139
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +5 -5
- package/dist/verify/subject.js +19 -19
- package/dist/verify/verify.js +94 -44
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +60 -91
- package/docs/architecture/browser-control.md +1 -1
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +68 -65
- package/docs/architecture/github-feedback-loop.md +2 -5
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +6 -6
- package/docs/architecture/terminal-product-route.md +70 -110
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +4 -7
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +42 -44
- package/docs/contracts/schemas.md +446 -368
- package/docs/contracts/study-analysis.md +7 -4
- package/docs/contracts/study-costs.md +28 -9
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/README.md +1 -1
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/examples/scorer/scorer.mjs +3 -3
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +64 -60
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab-format.d.ts +0 -8
- package/dist/cli/commands/lab-route-run.d.ts +0 -19
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -17
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -17
- package/dist/cli/commands/lab-run.d.ts +0 -9
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/lab/composition-rules.d.ts +0 -7
- package/dist/lab/config.d.ts +0 -7
- package/dist/lab/discover.d.ts +0 -65
- package/dist/lab/init-templates.js +0 -416
- package/dist/lab/keys.d.ts +0 -2
- package/dist/lab/parse/comms.d.ts +0 -12
- package/dist/lab/parse/execution.d.ts +0 -19
- package/dist/lab/parse/subject-state.d.ts +0 -30
- package/dist/lab/plan.d.ts +0 -19
- package/dist/lab/plan.js +0 -132
- package/dist/lab/preflight-probes.d.ts +0 -3
- package/dist/lab/preflight-result.d.ts +0 -7
- package/dist/lab/preflight.d.ts +0 -92
- package/dist/lab/route-inputs.d.ts +0 -28
- package/dist/lab/run-lab-options.d.ts +0 -28
- package/dist/lab/warnings.d.ts +0 -2
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/dist/run-lab.d.ts +0 -112
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- package/docs/roadmap/world-class-open-source-v0.md +0 -311
- /package/dist/{lab → study}/init-paths.d.ts +0 -0
- /package/dist/{lab → study}/init-paths.js +0 -0
- /package/dist/{lab → study}/init-plan.d.ts +0 -0
- /package/dist/{lab → study}/init-plan.js +0 -0
- /package/dist/{lab → study}/participant-assignment.d.ts +0 -0
- /package/dist/{lab → study}/participant-assignment.js +0 -0
- /package/dist/{lab → study}/persona.d.ts +0 -0
- /package/dist/{lab → study}/persona.js +0 -0
package/dist/observer/static.js
DELETED
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { constants as fsConstants } from "node:fs";
|
|
2
|
-
import { createServer } from "node:http";
|
|
3
|
-
import { lstat, open, realpath } from "node:fs/promises";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { buildArtifactSecurityHeaders } from "./http.js";
|
|
6
|
-
// Loopback-only host for the Observer static server. We never bind 0.0.0.0:
|
|
7
|
-
// the Observer surfaces local run evidence and must stay reachable only from
|
|
8
|
-
// the machine that owns the run bundle.
|
|
9
|
-
export const OBSERVER_STATIC_HOST = "127.0.0.1";
|
|
10
|
-
// Minimal extension -> content-type map. Kept dependency-free (no `mime`
|
|
11
|
-
// package) because the Observer ships a small, known set of asset kinds.
|
|
12
|
-
const CONTENT_TYPES = {
|
|
13
|
-
".html": "text/html; charset=utf-8",
|
|
14
|
-
".htm": "text/html; charset=utf-8",
|
|
15
|
-
".js": "text/javascript; charset=utf-8",
|
|
16
|
-
".mjs": "text/javascript; charset=utf-8",
|
|
17
|
-
".css": "text/css; charset=utf-8",
|
|
18
|
-
".json": "application/json; charset=utf-8",
|
|
19
|
-
".map": "application/json; charset=utf-8",
|
|
20
|
-
".svg": "image/svg+xml",
|
|
21
|
-
".png": "image/png",
|
|
22
|
-
".jpg": "image/jpeg",
|
|
23
|
-
".jpeg": "image/jpeg",
|
|
24
|
-
".webp": "image/webp",
|
|
25
|
-
".gif": "image/gif",
|
|
26
|
-
".ico": "image/x-icon",
|
|
27
|
-
".md": "text/markdown; charset=utf-8",
|
|
28
|
-
".ndjson": "application/x-ndjson; charset=utf-8",
|
|
29
|
-
".txt": "text/plain; charset=utf-8",
|
|
30
|
-
".woff": "font/woff",
|
|
31
|
-
".woff2": "font/woff2",
|
|
32
|
-
};
|
|
33
|
-
export function observerStaticContentType(filePath) {
|
|
34
|
-
return CONTENT_TYPES[path.extname(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Resolve, guard, and serve a single static request from `root`. Never throws:
|
|
38
|
-
* any unexpected failure is reported as a 500 so the connection always closes.
|
|
39
|
-
* Exported directly so the security guards can be unit-tested without binding a
|
|
40
|
-
* socket.
|
|
41
|
-
*/
|
|
42
|
-
export async function respondToObserverStaticRequest(options, request, response) {
|
|
43
|
-
applySecurityHeaders(response);
|
|
44
|
-
try {
|
|
45
|
-
const root = await pinStaticRoot(options.root);
|
|
46
|
-
await respondToPinnedObserverStaticRequest(root, options, request, response);
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
if (response.headersSent) {
|
|
50
|
-
response.end();
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
writeText(response, 500, "Observer request failed");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
async function respondToPinnedObserverStaticRequest(root, options, request, response) {
|
|
57
|
-
applySecurityHeaders(response);
|
|
58
|
-
const indexRelative = options.indexPath ?? "index.html";
|
|
59
|
-
try {
|
|
60
|
-
await assertPinnedStaticRoot(root);
|
|
61
|
-
const method = request.method ?? "GET";
|
|
62
|
-
if (method !== "GET" && method !== "HEAD") {
|
|
63
|
-
writeText(response, 405, "Method Not Allowed");
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
let pathname;
|
|
67
|
-
try {
|
|
68
|
-
pathname = new URL(request.url ?? "/", `http://${OBSERVER_STATIC_HOST}`).pathname;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
writeText(response, 400, "Bad Request");
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (pathname === "/" && options.redirectRootTo) {
|
|
75
|
-
const location = `/${options.redirectRootTo.replace(/^\/+/, "")}`;
|
|
76
|
-
response.writeHead(302, {
|
|
77
|
-
location,
|
|
78
|
-
"cache-control": "no-store",
|
|
79
|
-
"content-length": "0",
|
|
80
|
-
});
|
|
81
|
-
response.end();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
let decoded;
|
|
85
|
-
try {
|
|
86
|
-
decoded = decodeURIComponent(pathname);
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
writeText(response, 400, "Bad Request");
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
// Reject embedded NUL bytes outright rather than letting them reach the fs.
|
|
93
|
-
if (decoded.includes("\0")) {
|
|
94
|
-
writeText(response, 400, "Bad Request");
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
let relative = decoded.replace(/^\/+/, "");
|
|
98
|
-
if (relative === "" || relative.endsWith("/")) {
|
|
99
|
-
relative = `${relative}${indexRelative}`;
|
|
100
|
-
}
|
|
101
|
-
const target = path.resolve(root.physicalPath, relative);
|
|
102
|
-
if (!isPathInside(root.physicalPath, target)) {
|
|
103
|
-
writeText(response, 403, "Forbidden");
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
let info;
|
|
107
|
-
try {
|
|
108
|
-
info = await lstat(target);
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
writeText(response, 404, "Not Found");
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (info.isSymbolicLink()) {
|
|
115
|
-
writeText(response, 403, "Forbidden");
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
let filePath = target;
|
|
119
|
-
if (info.isDirectory()) {
|
|
120
|
-
filePath = path.resolve(target, indexRelative);
|
|
121
|
-
if (!isPathInside(root.physicalPath, filePath)) {
|
|
122
|
-
writeText(response, 403, "Forbidden");
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
const rawBody = await readContainedRegularFile(root, filePath);
|
|
127
|
-
const body = rawBody ? recordedObserverStaticBody(filePath, rawBody) : null;
|
|
128
|
-
if (!body) {
|
|
129
|
-
writeText(response, 404, "Not Found");
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
response.writeHead(200, {
|
|
133
|
-
"cache-control": "no-store",
|
|
134
|
-
"content-type": observerStaticContentType(filePath),
|
|
135
|
-
"content-length": String(body.byteLength),
|
|
136
|
-
});
|
|
137
|
-
if (method === "HEAD") {
|
|
138
|
-
response.end();
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
response.end(body);
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
if (response.headersSent) {
|
|
145
|
-
response.end();
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
writeText(response, 500, "Observer request failed");
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
function applySecurityHeaders(response) {
|
|
152
|
-
for (const [name, value] of Object.entries(buildArtifactSecurityHeaders()))
|
|
153
|
-
response.setHeader(name, value);
|
|
154
|
-
}
|
|
155
|
-
/** Static serving is recorded evidence. Neither JSON files nor inline HTML snapshots
|
|
156
|
-
* can carry a live process observation or grant provider-origin access. */
|
|
157
|
-
function recordedObserverStaticBody(filePath, body) {
|
|
158
|
-
const strip = (text) => {
|
|
159
|
-
try {
|
|
160
|
-
const data = JSON.parse(text);
|
|
161
|
-
if (!data ||
|
|
162
|
-
typeof data !== "object" ||
|
|
163
|
-
Array.isArray(data) ||
|
|
164
|
-
data.schema !== "humanish.observer-data.v1")
|
|
165
|
-
return null;
|
|
166
|
-
const projection = data;
|
|
167
|
-
delete projection.runtime;
|
|
168
|
-
if (Array.isArray(projection.streams)) {
|
|
169
|
-
for (const stream of projection.streams) {
|
|
170
|
-
if (!stream || typeof stream !== "object" || Array.isArray(stream))
|
|
171
|
-
continue;
|
|
172
|
-
const embed = stream.embed;
|
|
173
|
-
if (embed && typeof embed === "object" && !Array.isArray(embed))
|
|
174
|
-
delete embed.runtimeDesktop;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return JSON.stringify(projection)
|
|
178
|
-
.replace(/</g, "\\u003c")
|
|
179
|
-
.replace(/>/g, "\\u003e")
|
|
180
|
-
.replace(/&/g, "\\u0026");
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
if (path.basename(filePath) === "observer-data.json") {
|
|
187
|
-
const stripped = strip(body.toString("utf8"));
|
|
188
|
-
return stripped === null ? body : Buffer.from(stripped);
|
|
189
|
-
}
|
|
190
|
-
if (/\.html?$/i.test(filePath)) {
|
|
191
|
-
const html = body.toString("utf8");
|
|
192
|
-
// Identify Observer JSON by its schema, not an attribute spelling: HTML permits
|
|
193
|
-
// encoded ids and '>' inside quoted attributes. Other scripts remain byte-identical.
|
|
194
|
-
const sanitized = html.replace(/(<script\b(?:[^>"']|"[^"]*"|'[^']*')*>)([\s\S]*?)(<\/script\s*>)/gi, (match, start, json, end) => {
|
|
195
|
-
const stripped = strip(json);
|
|
196
|
-
return stripped === null ? match : `${start}${stripped}${end}`;
|
|
197
|
-
});
|
|
198
|
-
return sanitized === html ? body : Buffer.from(sanitized);
|
|
199
|
-
}
|
|
200
|
-
return body;
|
|
201
|
-
}
|
|
202
|
-
async function readContainedRegularFile(root, filePathInput) {
|
|
203
|
-
const filePath = path.resolve(filePathInput);
|
|
204
|
-
if (!isPathInside(root.physicalPath, filePath))
|
|
205
|
-
return null;
|
|
206
|
-
try {
|
|
207
|
-
await assertPinnedStaticRoot(root);
|
|
208
|
-
const expectedStats = await inspectContainedStaticFile(root, filePath);
|
|
209
|
-
if (!expectedStats) {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
const handle = await open(filePath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
213
|
-
try {
|
|
214
|
-
const openedStats = await handle.stat({ bigint: true });
|
|
215
|
-
if (!openedStats.isFile() ||
|
|
216
|
-
openedStats.nlink !== 1n ||
|
|
217
|
-
openedStats.dev !== expectedStats.dev ||
|
|
218
|
-
openedStats.ino !== expectedStats.ino) {
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
const recheckedStats = await inspectContainedStaticFile(root, filePath);
|
|
222
|
-
if (!recheckedStats ||
|
|
223
|
-
recheckedStats.dev !== expectedStats.dev ||
|
|
224
|
-
recheckedStats.ino !== expectedStats.ino) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
await assertPinnedStaticRoot(root);
|
|
228
|
-
const body = await handle.readFile();
|
|
229
|
-
await assertPinnedStaticRoot(root);
|
|
230
|
-
return body;
|
|
231
|
-
}
|
|
232
|
-
finally {
|
|
233
|
-
await handle.close();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
catch {
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
export function createObserverStaticHandler(options) {
|
|
241
|
-
let rootPromise;
|
|
242
|
-
return (request, response) => {
|
|
243
|
-
applySecurityHeaders(response);
|
|
244
|
-
rootPromise ??= pinStaticRoot(options.root);
|
|
245
|
-
void rootPromise
|
|
246
|
-
.then((root) => respondToPinnedObserverStaticRequest(root, options, request, response))
|
|
247
|
-
.catch(() => {
|
|
248
|
-
if (response.headersSent) {
|
|
249
|
-
response.end();
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
writeText(response, 500, "Observer request failed");
|
|
253
|
-
});
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
export async function serveObserverStatic(options) {
|
|
257
|
-
const entryPath = options.entryPath?.replace(/^\/+/, "") ?? "";
|
|
258
|
-
const handlerOptions = {
|
|
259
|
-
root: options.root,
|
|
260
|
-
...(options.indexPath === undefined ? {} : { indexPath: options.indexPath }),
|
|
261
|
-
...(entryPath ? { redirectRootTo: entryPath } : {}),
|
|
262
|
-
};
|
|
263
|
-
const root = await pinStaticRoot(options.root);
|
|
264
|
-
const handler = (request, response) => {
|
|
265
|
-
void respondToPinnedObserverStaticRequest(root, handlerOptions, request, response);
|
|
266
|
-
};
|
|
267
|
-
const server = createServer(handler);
|
|
268
|
-
const port = await listen(server, options.port ?? 0);
|
|
269
|
-
return {
|
|
270
|
-
url: `http://${OBSERVER_STATIC_HOST}:${port}/${entryPath}`,
|
|
271
|
-
port,
|
|
272
|
-
host: OBSERVER_STATIC_HOST,
|
|
273
|
-
close: () => closeServer(server),
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function writeText(response, status, message) {
|
|
277
|
-
const body = `${message}\n`;
|
|
278
|
-
response.writeHead(status, {
|
|
279
|
-
"cache-control": "no-store",
|
|
280
|
-
"content-type": "text/plain; charset=utf-8",
|
|
281
|
-
"content-length": String(Buffer.byteLength(body)),
|
|
282
|
-
});
|
|
283
|
-
response.end(body);
|
|
284
|
-
}
|
|
285
|
-
function isPathInside(root, candidate) {
|
|
286
|
-
const relative = path.relative(root, candidate);
|
|
287
|
-
return (relative === "" ||
|
|
288
|
-
(relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)));
|
|
289
|
-
}
|
|
290
|
-
async function inspectContainedStaticFile(root, filePath) {
|
|
291
|
-
const relative = path.relative(root.physicalPath, filePath);
|
|
292
|
-
if (!relative ||
|
|
293
|
-
relative === ".." ||
|
|
294
|
-
relative.startsWith(`..${path.sep}`) ||
|
|
295
|
-
path.isAbsolute(relative)) {
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
const segments = relative.split(path.sep).filter(Boolean);
|
|
299
|
-
let current = root.physicalPath;
|
|
300
|
-
let fileIdentity = null;
|
|
301
|
-
for (const [index, segment] of segments.entries()) {
|
|
302
|
-
current = path.join(current, segment);
|
|
303
|
-
const stats = await lstat(current, { bigint: true });
|
|
304
|
-
if (stats.isSymbolicLink())
|
|
305
|
-
return null;
|
|
306
|
-
if (index < segments.length - 1) {
|
|
307
|
-
if (!stats.isDirectory())
|
|
308
|
-
return null;
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
if (!stats.isFile() || stats.nlink !== 1n)
|
|
312
|
-
return null;
|
|
313
|
-
fileIdentity = { dev: stats.dev, ino: stats.ino };
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
if ((await realpath(filePath)) !== filePath)
|
|
317
|
-
return null;
|
|
318
|
-
return fileIdentity;
|
|
319
|
-
}
|
|
320
|
-
async function pinStaticRoot(rootInput) {
|
|
321
|
-
const physicalPath = await realpath(path.resolve(rootInput));
|
|
322
|
-
const stats = await lstat(physicalPath, { bigint: true });
|
|
323
|
-
if (stats.isSymbolicLink() || !stats.isDirectory()) {
|
|
324
|
-
throw new Error("Observer static roots must be physical directories.");
|
|
325
|
-
}
|
|
326
|
-
return Object.freeze({
|
|
327
|
-
birthtimeNs: stats.birthtimeNs,
|
|
328
|
-
dev: stats.dev,
|
|
329
|
-
ino: stats.ino,
|
|
330
|
-
physicalPath,
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
async function assertPinnedStaticRoot(root) {
|
|
334
|
-
const stats = await lstat(root.physicalPath, { bigint: true });
|
|
335
|
-
if (stats.isSymbolicLink() ||
|
|
336
|
-
!stats.isDirectory() ||
|
|
337
|
-
stats.birthtimeNs !== root.birthtimeNs ||
|
|
338
|
-
stats.dev !== root.dev ||
|
|
339
|
-
stats.ino !== root.ino ||
|
|
340
|
-
(await realpath(root.physicalPath)) !== root.physicalPath) {
|
|
341
|
-
throw new Error("Observer static root identity changed.");
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
function listen(server, port) {
|
|
345
|
-
return new Promise((resolve, reject) => {
|
|
346
|
-
server.once("error", reject);
|
|
347
|
-
server.listen(port, OBSERVER_STATIC_HOST, () => {
|
|
348
|
-
server.off("error", reject);
|
|
349
|
-
const address = server.address();
|
|
350
|
-
if (!address || typeof address === "string") {
|
|
351
|
-
reject(new Error("Observer static server did not bind to a TCP port."));
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
resolve(address.port);
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
function closeServer(server) {
|
|
359
|
-
return new Promise((resolve, reject) => {
|
|
360
|
-
server.close((error) => {
|
|
361
|
-
if (error) {
|
|
362
|
-
reject(error);
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
resolve();
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
}
|
package/dist/run-lab.d.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import type { LocalVmInput } from "./routes/computer-use/types.js";
|
|
2
|
-
import { type LateScorer } from "./lab/route-inputs.js";
|
|
3
|
-
import { type LabRoute } from "./lab/plan.js";
|
|
4
|
-
import type { LabDeps } from "./lab/lab-deps.js";
|
|
5
|
-
import type { RunLabDriving, RunLabHomes } from "./lab/run-lab-homes.js";
|
|
6
|
-
import { type LabConfig } from "./lab/types.js";
|
|
7
|
-
import type { ObserverResult } from "./observer/render.js";
|
|
8
|
-
import { type CuaActorLabResult } from "./routes/computer-use/types.js";
|
|
9
|
-
import { type ScriptedBrowserLabResult } from "./routes/scripted/types.js";
|
|
10
|
-
import { type ConcurrentSharedWorldLabResult } from "./routes/shared-world/types.js";
|
|
11
|
-
import { type TerminalProductLabResult } from "./routes/terminal/types.js";
|
|
12
|
-
import { type RunScorerProvenance } from "./run/bundle.js";
|
|
13
|
-
import { type RunResult } from "./run/results.js";
|
|
14
|
-
import { type RunLabProvenance } from "./run/status.js";
|
|
15
|
-
/**
|
|
16
|
-
* Runs a lab on its route. The options are checked against the route and mapped into the route's
|
|
17
|
-
* hook bags before anything runs. Each route closes the run it started on every exit through its
|
|
18
|
-
* own run scope (`src/run/run.ts`).
|
|
19
|
-
*/
|
|
20
|
-
export declare function runLab(config: LabConfig, options: InternalRunLabOptions, deps?: LabDeps): Promise<LabOutcome>;
|
|
21
|
-
/**
|
|
22
|
-
* runLab as the package exports it (`src/index.ts`): the public options only. A JavaScript caller
|
|
23
|
-
* that passes a field RunLabOptions no longer has is refused in the route's own result envelope
|
|
24
|
-
* before anything runs.
|
|
25
|
-
*/
|
|
26
|
-
export declare function runPackageLab(config: LabConfig, options: RunLabOptions): Promise<LabOutcome>;
|
|
27
|
-
/** A lab planned once: the route's refusal, or the run of its plan. */
|
|
28
|
-
export type PreparedLab = {
|
|
29
|
-
readonly ok: false;
|
|
30
|
-
readonly outcome: LabOutcome;
|
|
31
|
-
} | {
|
|
32
|
-
readonly ok: true;
|
|
33
|
-
/** Runs the plan. A scorer loaded after planning joins the run's hooks; it changes no plan. */
|
|
34
|
-
run(scorer?: LateScorer): Promise<LabOutcome>;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Normalizes the options and plans the lab once, so a caller can present a refusal before it loads
|
|
38
|
-
* anything the run needs. A local browser study's provider is bound first, so the plan is made with
|
|
39
|
-
* it, and its desktop goes to the computer-use run as `localVm`; with inProcess the caller drives
|
|
40
|
-
* the app in process and needs no desktop.
|
|
41
|
-
*/
|
|
42
|
-
export declare function prepareLab(config: LabConfig, options: InternalRunLabOptions, deps?: LabDeps): Promise<PreparedLab>;
|
|
43
|
-
/**
|
|
44
|
-
* What a package caller passes to runLab: the run's settings and the typed homes (`RunLabHomes`,
|
|
45
|
-
* `RunLabDriving`). Each wins over the config when provided.
|
|
46
|
-
*/
|
|
47
|
-
export type RunLabOptions = RunLabBase & RunLabHomes & RunLabDriving;
|
|
48
|
-
interface RunLabBase {
|
|
49
|
-
cwd: string;
|
|
50
|
-
runId?: string;
|
|
51
|
-
dryRun?: boolean;
|
|
52
|
-
open?: boolean;
|
|
53
|
-
/** Participant count override: preview participants or computer-use desktops. */
|
|
54
|
-
count?: number;
|
|
55
|
-
/** CUA fan-out only: create a new run for failed/selected participants from a prior run. */
|
|
56
|
-
rerun?: {
|
|
57
|
-
sourceRunId: string;
|
|
58
|
-
participantIds?: string[];
|
|
59
|
-
};
|
|
60
|
-
onObserverReady?: (observer: ObserverResult & {
|
|
61
|
-
ok: true;
|
|
62
|
-
}) => Promise<void> | void;
|
|
63
|
-
}
|
|
64
|
-
/** runLab's options inside the package: the public ones plus what only the CLI and tests set. */
|
|
65
|
-
export type InternalRunLabOptions = RunLabOptions & RunLabInternals;
|
|
66
|
-
interface RunLabInternals {
|
|
67
|
-
/**
|
|
68
|
-
* Which manifest this run came from (#455). planLab puts it on the plan, and the route reads
|
|
69
|
-
* plan.lab for the run's status record and bundle. Absent for a library caller that passes a
|
|
70
|
-
* LabConfig directly; that run records no lab.
|
|
71
|
-
*/
|
|
72
|
-
lab?: RunLabProvenance;
|
|
73
|
-
/**
|
|
74
|
-
* CONFIG-DECLARED scorer provenance (#316), forwarded alongside whichever hooks bag carries the
|
|
75
|
-
* loaded scorer. Its presence is the "declared" marker the terminal route reads to flip a
|
|
76
|
-
* status:"fail" verdict; the browser routes stamp it as evidence (they already flip). Core-computed
|
|
77
|
-
* (path + digest), never adopter-supplied; absent for library callers.
|
|
78
|
-
*/
|
|
79
|
-
scorerProvenance?: RunScorerProvenance;
|
|
80
|
-
/** The local VM study's desktop, analysis gate and signal, for a local browser lab. */
|
|
81
|
-
localVm?: LocalVmInput;
|
|
82
|
-
}
|
|
83
|
-
/** A run's result and the route it ran on. */
|
|
84
|
-
interface RouteOutcome<R extends LabRoute, T> {
|
|
85
|
-
route: R;
|
|
86
|
-
result: T;
|
|
87
|
-
}
|
|
88
|
-
export type LabOutcome = RouteOutcome<"preview", RunResult> | RouteOutcome<"computer-use", CuaActorLabResult> | RouteOutcome<"scripted", ScriptedBrowserLabResult> | RouteOutcome<"terminal", TerminalProductLabResult> | RouteOutcome<"shared-world", ConcurrentSharedWorldLabResult>;
|
|
89
|
-
/**
|
|
90
|
-
* A plan past its route's local checks that need no scorer: the refusal they returned, or the
|
|
91
|
-
* route's run, which takes a scorer loaded after them.
|
|
92
|
-
*/
|
|
93
|
-
export type AdmittedPlan<R extends LabRoute = LabRoute> = {
|
|
94
|
-
readonly ok: false;
|
|
95
|
-
readonly outcome: Extract<LabOutcome, {
|
|
96
|
-
route: R;
|
|
97
|
-
}>;
|
|
98
|
-
} | {
|
|
99
|
-
readonly ok: true;
|
|
100
|
-
run(scorer?: LateScorer): Promise<Extract<LabOutcome, {
|
|
101
|
-
route: R;
|
|
102
|
-
}>>;
|
|
103
|
-
};
|
|
104
|
-
/** The result of a run on route `R`, the `result` of that route's `LabOutcome`. */
|
|
105
|
-
export type LabResult<R extends LabRoute = LabRoute> = {
|
|
106
|
-
preview: RunResult;
|
|
107
|
-
"computer-use": CuaActorLabResult;
|
|
108
|
-
scripted: ScriptedBrowserLabResult;
|
|
109
|
-
terminal: TerminalProductLabResult;
|
|
110
|
-
"shared-world": ConcurrentSharedWorldLabResult;
|
|
111
|
-
}[R];
|
|
112
|
-
export {};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# Participant inboxes
|
|
2
|
-
|
|
3
|
-
This page describes local capture. For fresh hosted inboxes, see
|
|
4
|
-
[real email receiving](real-email-receiving.md); that route has a separate
|
|
5
|
-
parsed renderer, strict remote-asset blocking and private lease lifecycle.
|
|
6
|
-
|
|
7
|
-
The catch captures application mail without sending it to an external recipient.
|
|
8
|
-
humanish gives each participant an address and a matching
|
|
9
|
-
`/inbox/for/<address-digest>` URL. The same address scope applies to list, message,
|
|
10
|
-
plain view, latest-message and JSON routes. Going back from a missing message
|
|
11
|
-
stays in that scope. An unknown scope is empty; it never falls back to all mail.
|
|
12
|
-
A participant without an assigned address receives no inbox instruction.
|
|
13
|
-
|
|
14
|
-
This works with separate participant worlds, shared worlds, and an external catch.
|
|
15
|
-
Sharing an application world does not require sharing an inbox. If a lab deliberately
|
|
16
|
-
assigns the same address to two participants, both see that address's mail. Generated
|
|
17
|
-
addresses that collide after normalization are made distinct. A message addressed
|
|
18
|
-
to several participants appears in each recipient's inbox and retains its actual
|
|
19
|
-
To field.
|
|
20
|
-
|
|
21
|
-
`/inbox` remains available and is labeled **Shared operator inbox**. Address digests
|
|
22
|
-
are routing identifiers, not authentication credentials. The catch is study
|
|
23
|
-
infrastructure, not a mailbox service with hostile-tenant isolation. Keep its network
|
|
24
|
-
exposure appropriate for test mail. The read-only listener cannot expose the private
|
|
25
|
-
`/deliveries` drain, even when supplied a valid drain token. The capture listener
|
|
26
|
-
retains its existing optional bearer-token protection for that endpoint.
|
|
27
|
-
|
|
28
|
-
A standalone catch tracks its generated files. Reusing its directory with a changed
|
|
29
|
-
`--recipient` roster or an emptied delivery log removes obsolete message, latest and
|
|
30
|
-
recipient routes; unrelated files are untouched.
|
|
31
|
-
|
|
32
|
-
## Local browser studies
|
|
33
|
-
|
|
34
|
-
Run a catch on the same host as the local study:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
humanish comms catch --port 8025 --dir .humanish/mail-catch
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Configure your **app's** email transport to send to `http://127.0.0.1:8025`
|
|
41
|
-
using its supported HTTP send configuration, or add `--smtp-port 1025` and
|
|
42
|
-
point its SMTP transport at `127.0.0.1:1025`. humanish does not change an
|
|
43
|
-
already-running app's environment. No real mailbox-provider credentials are
|
|
44
|
-
needed. This captures mail sent by that app; it does not receive arbitrary
|
|
45
|
-
internet email.
|
|
46
|
-
|
|
47
|
-
Add this to an existing local `app-url` lab:
|
|
48
|
-
|
|
49
|
-
```yaml
|
|
50
|
-
comms:
|
|
51
|
-
email:
|
|
52
|
-
external:
|
|
53
|
-
catchBaseUrl: http://127.0.0.1:8025
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Then run `humanish doctor --lab <lab>` and `humanish run <lab>`. Omit
|
|
57
|
-
`recipients` to assign an address per participant automatically, or declare explicit
|
|
58
|
-
`{ lane, address }` entries for an existing roster. The participant receives its
|
|
59
|
-
address and inbox URL in its mission. Verification links keep their original
|
|
60
|
-
app origin; ensure they target the loopback app port selected by the lab.
|
|
61
|
-
|
|
62
|
-
Each local desktop forwards a separate host-owned read-only proxy for its
|
|
63
|
-
assigned recipient. Other recipient routes, the operator inbox, mail sends and
|
|
64
|
-
the private delivery drain are unavailable through that proxy. The study closes
|
|
65
|
-
these proxies with its desktops and leaves your catch running. Host-side
|
|
66
|
-
collection uses the existing digest-only comms evidence. Supported captured
|
|
67
|
-
images and explicit unavailable-image placeholders work as described below.
|
|
68
|
-
|
|
69
|
-
The local path supports captured email only. Provider-backed real receiving
|
|
70
|
-
retains its separate hosted-route and management-credential requirements.
|
|
71
|
-
|
|
72
|
-
## Existing external catches
|
|
73
|
-
|
|
74
|
-
Upgrade the humanish installation that runs `humanish comms catch` and **restart that
|
|
75
|
-
catch process**, as well as upgrading the installation that starts the study. Updating
|
|
76
|
-
only the study client leaves an older catch without participant routes.
|
|
77
|
-
|
|
78
|
-
Before allocating participants, the client checks `/health` on both `catchBaseUrl`
|
|
79
|
-
and a distinct `inboxBaseUrl`. Each must return the normal service marker and
|
|
80
|
-
`capabilities: ["recipient-inbox-v1", ...]`. Missing, malformed or older responses
|
|
81
|
-
fail admission with an upgrade/restart instruction. Existing email capture endpoints
|
|
82
|
-
and unscoped operator URLs remain available; their payload contracts are unchanged.
|
|
83
|
-
|
|
84
|
-
## Captured and remote images
|
|
85
|
-
|
|
86
|
-
The SMTP catch preserves MIME parts with a Content-ID when they contain PNG, JPEG,
|
|
87
|
-
GIF or WebP bytes. The generic `/emails` payload can also carry runtime-only
|
|
88
|
-
`inlineImages` entries with `contentId`, `contentType` and `base64`. Provider-specific
|
|
89
|
-
attachment fields are not converted; unsupported or missing CID references show an
|
|
90
|
-
explicit unavailable-image placeholder instead of pretending capture succeeded.
|
|
91
|
-
|
|
92
|
-
Captured images are limited to 12 entries, 1 MiB each and 2 MiB total. The renderer
|
|
93
|
-
checks canonical base64 and the declared raster format's signature before creating a
|
|
94
|
-
data URL. This is not a full image decoder; malformed raster content can still fail
|
|
95
|
-
in the browser. Inline data URLs receive the same per-image checks. SVG, arbitrary
|
|
96
|
-
attachment URLs and local paths are not fetched or converted.
|
|
97
|
-
|
|
98
|
-
HTTP(S) images remain browser loads with `no-referrer`. humanish does not fetch or
|
|
99
|
-
proxy them server-side. Relative image URLs use the existing declared origin-rewrite
|
|
100
|
-
map when available; otherwise they receive an explicit placeholder. Remote URLs that
|
|
101
|
-
return errors retain the browser's alt-text fallback. The renderer does not claim to
|
|
102
|
-
repair a dead URL. The inbox retains `script-src 'none'` and the existing HTML
|
|
103
|
-
neutralization and origin-rewrite protections.
|
|
104
|
-
|
|
105
|
-
Raw mail and image bytes remain runtime catch data. Persisted comms evidence remains
|
|
106
|
-
digest-only; adding image capture does not add raw attachments to the run artifact.
|
|
107
|
-
|
|
108
|
-
## Reproduce the contract
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
pnpm exec vitest run tests/comms/ tests/substrates/local/captured-inbox.test.ts
|
|
112
|
-
pnpm exec tsx scripts/comms-inbox-proof.ts
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
The browser proof starts owned loopback HTTP, read-only inbox and SMTP listeners,
|
|
116
|
-
sends fictional multipart mail through the real MIME parser, and renders two recipient
|
|
117
|
-
inboxes in Chromium at desktop and phone sizes. It checks decoded CID/data/remote
|
|
118
|
-
images, unavailable sources, a genuine remote 404, recipient isolation across HTML
|
|
119
|
-
and JSON, navigation, script blocking, referrer suppression, directory reuse and drain
|
|
120
|
-
access. Screenshots and a machine-readable receipt are saved under the ignored
|
|
121
|
-
`.humanish/comms-inbox-proof/` directory. It uses no external email delivery, paid model
|
|
122
|
-
calls or hosted desktop, and makes no claim about those providers.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Optional desktop recording
|
|
2
|
-
|
|
3
|
-
humanish keeps screenshots, actions, participant feedback and analysis by default.
|
|
4
|
-
For continuous playback, opt into a desktop video:
|
|
5
|
-
|
|
6
|
-
```yaml
|
|
7
|
-
execution:
|
|
8
|
-
desktop:
|
|
9
|
-
recording: { audio: true }
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Set `audio: false` for screen-only video. Omit `recording` to keep the lightweight
|
|
13
|
-
snapshot recording. This applies to independent computer-use desktop participants on
|
|
14
|
-
local Firecracker and E2B; scripted-browser, shared-world and in-process executors
|
|
15
|
-
do not consume this setting and reject it before execution.
|
|
16
|
-
|
|
17
|
-
Recording does not enable a camera, speech synthesis or speech recognition.
|
|
18
|
-
Those remain separate [participant media](participant-media.md) options. With
|
|
19
|
-
audio enabled, microphone input and speaker output are mixed into one AAC track.
|
|
20
|
-
`audioSources` identifies the capture points feeding that mix, not separate
|
|
21
|
-
retained tracks. The microphone can be silent when speech is not configured.
|
|
22
|
-
A recorded microphone signal proves what was offered to the browser, not what
|
|
23
|
-
another person received. Confirm reciprocal delivery from the other
|
|
24
|
-
participant's evidence.
|
|
25
|
-
|
|
26
|
-
## Capture and playback
|
|
27
|
-
|
|
28
|
-
The desktop runs FFmpeg against its X display. MP4 carries H.264 video and optional
|
|
29
|
-
AAC audio. Recording stops and streams to the run directory before desktop cleanup.
|
|
30
|
-
Both providers use the same encoding settings and artifact metadata. Video encoding
|
|
31
|
-
uses the capture input’s microsecond time base, preserving closely spaced captures
|
|
32
|
-
and their offsets rather than rounding them to the nominal frame interval.
|
|
33
|
-
Explicit variable-frame-rate output preserves gaps without filling them with
|
|
34
|
-
duplicate frames across the supported FFmpeg versions. The recording
|
|
35
|
-
mix disables playback rewinds to avoid the null sink's initial two-second buffer. The local
|
|
36
|
-
runtime transfers one bounded file over its existing owner connection; E2B uses
|
|
37
|
-
the SDK's streaming file download. Participant tools cannot request arbitrary files.
|
|
38
|
-
|
|
39
|
-
Local recording uses the existing optional media runtime archive. This keeps the
|
|
40
|
-
browser-only download unchanged, but the optional archive also contains speech
|
|
41
|
-
assets even when speech is disabled. Recording alone does not start Whisper or
|
|
42
|
-
text-to-speech. E2B's stock desktop already has the recording dependencies; a custom
|
|
43
|
-
template must provide compatible FFmpeg, X11 and, for audio, PulseAudio tools.
|
|
44
|
-
|
|
45
|
-
Observer uses the existing study clock to play the selected participant's video.
|
|
46
|
-
Scrubbing, opening a participant and returning to the grid preserve study time.
|
|
47
|
-
The grid continues to show lightweight captures; only the selected participant
|
|
48
|
-
has audible playback. Outside the retained media interval, Observer shows that
|
|
49
|
-
video is unavailable rather than extending its coverage. Old screenshot-only runs
|
|
50
|
-
continue to work.
|
|
51
|
-
|
|
52
|
-
Capture still begins after device and transport startup. An audio track can contain
|
|
53
|
-
silence before a cold source delivers sound; early dispatch of speech or playback
|
|
54
|
-
does not itself prove audible capture. Preserve these offsets when reviewing early
|
|
55
|
-
events. The startup correction does not reconstruct missing frames or audio in
|
|
56
|
-
existing files. Variable guest execution stalls can still leave frame gaps; the
|
|
57
|
-
recorded timestamps preserve those gaps. A regularly timestamped video can also
|
|
58
|
-
show an unchanged screen while the application stalls. Visual/audio event timing
|
|
59
|
-
depends on source delivery and guest execution; timestamp precision does not
|
|
60
|
-
guarantee simultaneous delivery. See #854 for the remaining investigation.
|
|
61
|
-
|
|
62
|
-
The file and its measured interval are recorded in `streams[].recording` and a
|
|
63
|
-
`recording` artifact entry. A recorder failure warns and preserves screenshots,
|
|
64
|
-
actions and feedback; it does not fail an otherwise useful participant. Incomplete
|
|
65
|
-
but playable media is labeled partial. Forced VM loss may leave no retrievable
|
|
66
|
-
video. Analysis continues to use the existing screenshot and text evidence; it
|
|
67
|
-
does not inspect the MP4.
|
|
68
|
-
|
|
69
|
-
## Local evidence and exports
|
|
70
|
-
|
|
71
|
-
Video and audio are raw local evidence. `policies.redactScreenshots` does not redact
|
|
72
|
-
them, and verification keeps a run with continuous media `local_only`. The recorder
|
|
73
|
-
has a 128 MiB per-participant file limit; a retained size-limited recording is partial.
|
|
74
|
-
Encoding consumes additional CPU, memory and disk, so snapshots remain the default.
|
|
75
|
-
|
|
76
|
-
`humanish export --local-only` produces the existing portable HTML with screenshots
|
|
77
|
-
and text, excludes continuous media and displays that exclusion. Open the original
|
|
78
|
-
run through `humanish watch` or `humanish serve` to play its video. Redacted bundle
|
|
79
|
-
export does not redact video/audio and rejects these runs. There is no new portable
|
|
80
|
-
video format or automatic audio/video redaction in this feature.
|