humanish 0.107.0 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +22 -17
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +51 -44
- package/README.md +145 -172
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +8 -6
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +2 -2
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +16 -16
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/admission-limit.d.ts +1 -1
- package/dist/actors/computer-use/admission-limit.js +1 -1
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +10 -10
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/ending.d.ts +5 -5
- package/dist/actors/computer-use/loop/ending.js +7 -7
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +9 -9
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +1 -1
- package/dist/actors/computer-use/loop/session.js +3 -3
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +9 -8
- package/dist/actors/computer-use/loop/types.d.ts +25 -23
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +11 -8
- package/dist/actors/computer-use/openai-provider.js +45 -34
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/contract.d.ts +78 -43
- package/dist/actors/contract.js +29 -23
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +10 -9
- package/dist/actors/local-agent/cli.d.ts +8 -6
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +6 -6
- package/dist/actors/registry.d.ts +10 -10
- package/dist/actors/registry.js +18 -17
- package/dist/actors/scripted-browser/actor.d.ts +8 -8
- package/dist/actors/scripted-browser/actor.js +16 -16
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/service.js +5 -5
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +54 -33
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/lab-format.d.ts +5 -4
- package/dist/cli/commands/lab-format.js +35 -23
- package/dist/cli/commands/lab-route-computer-use.js +6 -7
- package/dist/cli/commands/lab-route-preview.js +4 -3
- package/dist/cli/commands/lab-route-shared-world.js +3 -3
- package/dist/cli/commands/lab-run.js +10 -11
- package/dist/cli/commands/lab-scorer.d.ts +2 -2
- package/dist/cli/commands/lab-scorer.js +1 -1
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.js +147 -108
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +137 -138
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +26 -21
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +182 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +21 -21
- package/dist/cli/commands/watch.js +60 -75
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +15 -5
- package/dist/cli/doctor.js +103 -48
- package/dist/cli/first-run-path.d.ts +12 -10
- package/dist/cli/first-run-path.js +30 -28
- package/dist/cli/io.d.ts +41 -6
- package/dist/cli/io.js +97 -22
- package/dist/cli/observer-follow.d.ts +2 -2
- package/dist/cli/observer-follow.js +5 -6
- package/dist/cli/orientation.d.ts +6 -3
- package/dist/cli/orientation.js +43 -39
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +109 -40
- package/dist/cli/telemetry.d.ts +15 -15
- package/dist/cli/telemetry.js +48 -40
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.js +2 -2
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +2 -2
- package/dist/comms/fake-inbox.js +2 -2
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +36 -37
- package/dist/comms/sandbox-catch.js +34 -35
- package/dist/comms/setup.js +42 -8
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +36 -78
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +7 -8
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/guest/chromium-text.js +2 -2
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/runtime.js +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +8 -6
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/lab/adapter-extension.d.ts +7 -7
- package/dist/lab/adapter-extension.js +13 -36
- package/dist/lab/adapter-scorer-loader.d.ts +7 -7
- package/dist/lab/adapter-scorer-loader.js +32 -32
- package/dist/lab/composition-rules.js +42 -42
- package/dist/lab/config.js +65 -25
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +8 -8
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +117 -57
- package/dist/lab/doctor.d.ts +10 -3
- package/dist/lab/doctor.js +47 -9
- package/dist/lab/init-templates.js +147 -147
- package/dist/lab/init.d.ts +1 -1
- package/dist/lab/init.js +41 -9
- package/dist/lab/keys.d.ts +2 -0
- package/dist/lab/keys.js +42 -8
- package/dist/lab/lab-deps.d.ts +7 -12
- package/dist/lab/parse/actors.js +9 -9
- package/dist/lab/parse/comms.js +5 -5
- package/dist/lab/parse/execution.js +13 -13
- package/dist/lab/parse/study-v3.d.ts +23 -0
- package/dist/lab/parse/study-v3.js +259 -0
- package/dist/lab/parse/subject-state.d.ts +7 -7
- package/dist/lab/parse/subject-state.js +16 -16
- package/dist/lab/parse/subject.js +28 -28
- package/dist/lab/parse/values.d.ts +1 -1
- package/dist/lab/parse/values.js +3 -3
- package/dist/lab/persona-resolve.d.ts +4 -4
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/plan-participants.d.ts +2 -2
- package/dist/lab/plan-types.d.ts +4 -4
- package/dist/lab/plan.d.ts +1 -7
- package/dist/lab/plan.js +10 -41
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -4
- package/dist/lab/preflight.d.ts +7 -5
- package/dist/lab/preflight.js +5 -5
- package/dist/lab/routing.d.ts +31 -25
- package/dist/lab/routing.js +60 -29
- package/dist/lab/run-lab-events.d.ts +0 -3
- package/dist/lab/run-lab-events.js +0 -6
- package/dist/lab/run-lab-homes.d.ts +22 -10
- package/dist/lab/run-lab-homes.js +5 -1
- package/dist/lab/run-lab-options.d.ts +1 -1
- package/dist/lab/run-lab-options.js +16 -13
- package/dist/lab/summary.d.ts +7 -6
- package/dist/lab/summary.js +10 -10
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +101 -95
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +13 -13
- package/dist/lab/validation.js +44 -42
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +61 -33
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +6 -6
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +1 -1
- package/dist/observer/library.js +4 -2
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +10 -5
- package/dist/observer/run-routes.d.ts +3 -3
- package/dist/observer/run-routes.js +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +15 -15
- package/dist/routes/computer-use/bundle.js +3 -3
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
- package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
- package/dist/routes/computer-use/external-comms.d.ts +1 -1
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +18 -18
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-flush.d.ts +1 -1
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +4 -2
- package/dist/routes/computer-use/live-phase.js +6 -6
- package/dist/routes/computer-use/local-vm.js +1 -1
- package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
- package/dist/routes/computer-use/participant-desktop.js +4 -4
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +9 -9
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +31 -13
- package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
- package/dist/routes/computer-use/participant-prompt.js +6 -6
- package/dist/routes/computer-use/participant-runs.d.ts +7 -7
- package/dist/routes/computer-use/participant-runs.js +13 -13
- package/dist/routes/computer-use/plan.js +22 -22
- package/dist/routes/computer-use/preflight.js +21 -21
- package/dist/routes/computer-use/rerun-selection.js +1 -1
- package/dist/routes/computer-use/result.js +11 -11
- package/dist/routes/computer-use/route.d.ts +2 -1
- package/dist/routes/computer-use/route.js +15 -14
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +31 -31
- package/dist/routes/computer-use/setup.d.ts +1 -1
- package/dist/routes/computer-use/setup.js +17 -18
- package/dist/routes/computer-use/single-bundle.d.ts +7 -7
- package/dist/routes/computer-use/single-bundle.js +28 -30
- package/dist/routes/computer-use/subject-projection.d.ts +1 -1
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +40 -42
- package/dist/routes/computer-use/types.js +10 -10
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -4
- package/dist/routes/scripted/bundle.d.ts +2 -2
- package/dist/routes/scripted/bundle.js +13 -12
- package/dist/routes/scripted/plan.d.ts +1 -1
- package/dist/routes/scripted/plan.js +9 -9
- package/dist/routes/scripted/result.js +5 -5
- package/dist/routes/scripted/route.js +5 -6
- package/dist/routes/scripted/scenario.js +2 -2
- package/dist/routes/scripted/setup.js +7 -7
- package/dist/routes/scripted/subject.js +1 -1
- package/dist/routes/scripted/surface-records.js +3 -3
- package/dist/routes/scripted/types.d.ts +3 -5
- package/dist/routes/scripted/types.js +1 -1
- package/dist/routes/shared-world/bundle-records.js +9 -8
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +40 -38
- package/dist/routes/shared-world/checkpoints.d.ts +1 -1
- package/dist/routes/shared-world/checkpoints.js +1 -1
- package/dist/routes/shared-world/comms.d.ts +5 -5
- package/dist/routes/shared-world/comms.js +14 -14
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +7 -6
- package/dist/routes/shared-world/participant-specs.js +31 -24
- package/dist/routes/shared-world/plan.js +7 -7
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.js +14 -13
- package/dist/routes/shared-world/result.js +20 -21
- package/dist/routes/shared-world/route.js +23 -22
- package/dist/routes/shared-world/setup.d.ts +3 -3
- package/dist/routes/shared-world/setup.js +4 -4
- package/dist/routes/shared-world/types.d.ts +30 -28
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +3 -3
- package/dist/routes/terminal/adapter.js +5 -5
- package/dist/routes/terminal/bundle.d.ts +3 -3
- package/dist/routes/terminal/bundle.js +22 -21
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +7 -7
- package/dist/routes/terminal/dry-run.js +4 -4
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/live-finish.js +3 -3
- package/dist/routes/terminal/live-sandbox.js +12 -13
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.js +11 -11
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.js +8 -8
- package/dist/routes/terminal/route.js +6 -7
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.js +8 -7
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +2 -2
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +26 -28
- package/dist/routes/terminal/types.js +3 -3
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +46 -46
- package/dist/run/bundle.js +2 -1
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.js +7 -1
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +18 -18
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +20 -13
- package/dist/run/projection.d.ts +14 -14
- package/dist/run/projection.js +15 -15
- package/dist/run/reclaim.js +2 -2
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +8 -6
- package/dist/run/run-index.js +15 -16
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +5 -4
- package/dist/run/run.js +1 -1
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +36 -35
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +6 -6
- package/dist/run/stats.d.ts +12 -6
- package/dist/run/stats.js +116 -58
- package/dist/run/status.d.ts +8 -29
- package/dist/run/status.js +5 -27
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +6 -6
- package/dist/run/study-provenance.d.ts +47 -0
- package/dist/run/study-provenance.js +63 -0
- package/dist/run/study-result.d.ts +16 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-lab.d.ts +7 -7
- package/dist/run-lab.js +1 -3
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +43 -0
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/subject/clone.d.ts +1 -1
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.js +1 -1
- package/dist/subject/local-tree.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +8 -9
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +5 -5
- package/dist/subject/steps.js +4 -4
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
- package/dist/substrates/e2b/desktop-browser.js +8 -8
- package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
- package/dist/substrates/e2b/desktop-cdp.js +8 -8
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
- package/dist/substrates/e2b/desktop-executor.js +1 -1
- package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
- package/dist/substrates/e2b/desktop-geometry.js +7 -7
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/sandbox.d.ts +1 -1
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +6 -6
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +16 -16
- package/dist/tui/contract.js +10 -10
- package/dist/tui/launch.d.ts +4 -4
- package/dist/tui/launch.js +18 -19
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +82 -82
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +92 -43
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +56 -87
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +61 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +5 -5
- package/docs/architecture/terminal-product-route.md +67 -107
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +2 -5
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +45 -44
- package/docs/contracts/schemas.md +421 -362
- package/docs/contracts/study-analysis.md +3 -3
- package/docs/contracts/study-costs.md +11 -7
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +60 -58
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- package/docs/roadmap/world-class-open-source-v0.md +0 -311
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { concurrencyFacts } from "../run/shared-world-evidence.js";
|
|
2
2
|
import { COMMAND_DIGEST_PATTERN, SHARED_WORLD_STATESERIES_KEYS, planeProvenanceFindings, sharedWorldCommonFindings, } from "../run/shared-world-shape.js";
|
|
3
3
|
import { isRecord } from "../run/type-guards.js";
|
|
4
|
-
//
|
|
5
|
-
// sequential claim leaking into a concurrent bundle == overclaim). verify needs
|
|
4
|
+
// Concurrent: the required set (all must be present) and a forbidden set (any present == a
|
|
5
|
+
// sequential claim leaking into a concurrent bundle == overclaim). verify needs both checks, because
|
|
6
6
|
// presence-only would let an incoherent union pass.
|
|
7
7
|
const CONCURRENT_REQUIRED_LIMITS = [
|
|
8
8
|
"concurrent",
|
|
@@ -13,12 +13,12 @@ const CONCURRENT_REQUIRED_LIMITS = [
|
|
|
13
13
|
"state-change-not-isolated-to-actors",
|
|
14
14
|
];
|
|
15
15
|
const CONCURRENT_FORBIDDEN_LIMITS = ["sequential-only", "no-concurrent-races"];
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// operator-attested
|
|
19
|
-
// cannot claim synthetic on a real site), the
|
|
20
|
-
// in-sandbox filesystem to digest), and concurrency evidenced by temporal co-occupancy
|
|
21
|
-
//
|
|
16
|
+
// External-public plane class: the downgrade required set. Keeps the concurrent family and adds
|
|
17
|
+
// the mandatory disclosures for a plane the harness does not own: the
|
|
18
|
+
// operator-attested target the harness does not control, the absence of a synthetic attestation (you
|
|
19
|
+
// cannot claim synthetic on a real site), the absence of an authoritative shared-state proof (no
|
|
20
|
+
// in-sandbox filesystem to digest), and concurrency evidenced by temporal co-occupancy only. Verify
|
|
21
|
+
// fails closed if any is missing (an absent downgrade limit overclaims).
|
|
22
22
|
const EXTERNAL_PUBLIC_EXTRA_LIMITS = [
|
|
23
23
|
"external-public-plane",
|
|
24
24
|
"operator-attested-target-not-harness-controlled",
|
|
@@ -26,7 +26,7 @@ const EXTERNAL_PUBLIC_EXTRA_LIMITS = [
|
|
|
26
26
|
"no-authoritative-shared-state-proof",
|
|
27
27
|
"concurrency-by-temporal-co-occupancy-only",
|
|
28
28
|
];
|
|
29
|
-
// Any seeded/synthetic limit on this class is a getHost claim leaking onto a real public site
|
|
29
|
+
// Any seeded/synthetic limit on this class is a getHost claim leaking onto a real public site; forbid
|
|
30
30
|
// it alongside the sequential family. (A synthetic attestation on a plane the harness did not seed is a lie.)
|
|
31
31
|
const EXTERNAL_PUBLIC_FORBIDDEN_LIMITS = [
|
|
32
32
|
"sequential-only",
|
|
@@ -35,17 +35,17 @@ const EXTERNAL_PUBLIC_FORBIDDEN_LIMITS = [
|
|
|
35
35
|
"synthetic",
|
|
36
36
|
];
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
* shape (laneWindows + stateSeries + outcomes,
|
|
38
|
+
* Concurrent branch: N personas drove one getHost-exposed plane at once. Verify fail-closed: the
|
|
39
|
+
* shape (laneWindows + stateSeries + outcomes, no timeline); the required and forbidden
|
|
40
40
|
* attributionLimits; the harness-minted getHost target every actor drove; the synthetic-subject
|
|
41
41
|
* provenance gate; digest-only state series with the allowed-keys tripwire; single-plane
|
|
42
42
|
* provenance; and the concurrency-on-pass gate (genuine overlap and a state delta at or after an
|
|
43
43
|
* overlap start).
|
|
44
44
|
*/
|
|
45
45
|
export function concurrentSharedWorldFindings(bundle, sw) {
|
|
46
|
-
// The
|
|
46
|
+
// The plane-class discriminator. Absent means the provisioned-getHost plane. Every
|
|
47
47
|
// getHost-specific assertion (hostDigest, exposure: synthetic, seeded provenance, state-delta on
|
|
48
|
-
// pass) is gated on this
|
|
48
|
+
// pass) is gated on this, so it never leaks onto the external-public class, and the external-public
|
|
49
49
|
// assertions never leak onto getHost.
|
|
50
50
|
const planeClass = sw.planeClass;
|
|
51
51
|
if (planeClass === "external-public") {
|
|
@@ -61,15 +61,15 @@ export function concurrentSharedWorldFindings(bundle, sw) {
|
|
|
61
61
|
}
|
|
62
62
|
const participantIdOf = (window) => typeof window.roleId === "string" ? window.roleId : "(unnamed)";
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
65
|
-
* in-sandbox. The harness
|
|
64
|
+
* Provisioned-getHost concurrent branch: a clone/local-tree subject served and getHost-exposed
|
|
65
|
+
* in-sandbox. The harness minted the host, so this asserts the synthetic-seeded attestation, the
|
|
66
66
|
* harness-minted host identity, and an authoritative in-sandbox checkpoint state-delta on pass.
|
|
67
67
|
*/
|
|
68
68
|
function provisionedGetHostConcurrentFindings(bundle, sw) {
|
|
69
69
|
const findings = sharedWorldCommonFindings(bundle, sw);
|
|
70
|
-
// Shape coherence: concurrent carries laneWindows/stateSeries/outcomes
|
|
70
|
+
// Shape coherence: concurrent carries laneWindows/stateSeries/outcomes and no timeline.
|
|
71
71
|
if (Array.isArray(sw.timeline)) {
|
|
72
|
-
findings.push("a concurrent shared-world bundle must
|
|
72
|
+
findings.push("a concurrent shared-world bundle must not carry a sequential timeline (topologyMode mismatch)");
|
|
73
73
|
}
|
|
74
74
|
const windows = recordsOf(sw.laneWindows);
|
|
75
75
|
const stateSeries = recordsOf(sw.stateSeries);
|
|
@@ -83,10 +83,10 @@ function provisionedGetHostConcurrentFindings(bundle, sw) {
|
|
|
83
83
|
if (windows === null || stateSeries === null || outcomes === null) {
|
|
84
84
|
return findings; // can't reason further without the core series
|
|
85
85
|
}
|
|
86
|
-
// Required limits all present
|
|
86
|
+
// Required limits all present and forbidden limits all absent.
|
|
87
87
|
findings.push(...attributionLimitFindings(sw, CONCURRENT_REQUIRED_LIMITS, CONCURRENT_FORBIDDEN_LIMITS, {
|
|
88
|
-
missing: (limit) => `attributionLimits is missing the
|
|
89
|
-
forbidden: (limit) => `attributionLimits carries the
|
|
88
|
+
missing: (limit) => `attributionLimits is missing the required concurrent disclosure "${limit}"; without it the bundle claims more than the run can show`,
|
|
89
|
+
forbidden: (limit) => `attributionLimits carries the disclosure "${limit}", which a concurrent run cannot claim: it describes a sequential guarantee`,
|
|
90
90
|
}), ...participantCoverageFindings(sw, windows, outcomes), ...windowFindings(bundle, windows, "the host it drove"), ...getHostPlaneFindings(bundle, sw, windows), ...stateSeriesFindings(stateSeries), ...concurrencyOnPassFindings(bundle, windows, stateSeries));
|
|
91
91
|
return findings;
|
|
92
92
|
}
|
|
@@ -103,7 +103,7 @@ function attributionLimitFindings(sw, required, forbidden, messages) {
|
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
105
|
* Phantom/dropped role: laneWindows + outcomes each cover exactly roleCount (actors are
|
|
106
|
-
*
|
|
106
|
+
* independent: none are blocked by another, so all N produce a window + outcome).
|
|
107
107
|
*/
|
|
108
108
|
function participantCoverageFindings(sw, windows, outcomes) {
|
|
109
109
|
const findings = [];
|
|
@@ -139,7 +139,7 @@ function windowFindings(bundle, windows, routeTarget) {
|
|
|
139
139
|
return findings;
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
142
|
-
* The getHost plane: every actor drove
|
|
142
|
+
* The getHost plane: every actor drove exactly the harness-minted host, the subject is
|
|
143
143
|
* attested synthetic and seeded, and every laneWindow shares the plane's provenance.
|
|
144
144
|
*/
|
|
145
145
|
function getHostPlaneFindings(bundle, sw, windows) {
|
|
@@ -161,12 +161,12 @@ function getHostPlaneFindings(bundle, sw, windows) {
|
|
|
161
161
|
// Synthetic-subject provenance gate (a getHost URL is internet-reachable; real/external data
|
|
162
162
|
// behind it is the hazard). Author attestation + a seeded provenance check.
|
|
163
163
|
if (plane.exposure !== "synthetic") {
|
|
164
|
-
findings.push('sharedWorld.plane.exposure must be "synthetic"
|
|
164
|
+
findings.push('sharedWorld.plane.exposure must be "synthetic": the study must declare that a subject at a public sandbox URL holds synthetic seeded data. humanish records that declaration and cannot check it');
|
|
165
165
|
}
|
|
166
166
|
if (bundle.subject?.state.provenance !== "seeded") {
|
|
167
|
-
findings.push(`
|
|
167
|
+
findings.push(`a provisioned shared-world run needs subject.state.provenance == "seeded" (got "${bundle.subject?.state.provenance ?? "absent"}"): external, unpinned or undeclared data at a public sandbox URL is not allowed`);
|
|
168
168
|
}
|
|
169
|
-
// Single-plane provenance: every laneWindow shares
|
|
169
|
+
// Single-plane provenance: every laneWindow shares one (commit, seedDigest) matching plane.
|
|
170
170
|
findings.push(...planeProvenanceFindings(windows, plane, {
|
|
171
171
|
items: "laneWindows",
|
|
172
172
|
item: "laneWindow",
|
|
@@ -174,7 +174,7 @@ function getHostPlaneFindings(bundle, sw, windows) {
|
|
|
174
174
|
}));
|
|
175
175
|
return findings;
|
|
176
176
|
}
|
|
177
|
-
/** stateSeries is
|
|
177
|
+
/** stateSeries is digest-only with the allowed-keys tripwire (no per-delta→actor field). */
|
|
178
178
|
function stateSeriesFindings(stateSeries) {
|
|
179
179
|
const findings = [];
|
|
180
180
|
for (const snapshot of stateSeries) {
|
|
@@ -186,7 +186,7 @@ function stateSeriesFindings(stateSeries) {
|
|
|
186
186
|
}
|
|
187
187
|
for (const key of Object.keys(snapshot)) {
|
|
188
188
|
if (!SHARED_WORLD_STATESERIES_KEYS.has(key)) {
|
|
189
|
-
findings.push(`a stateSeries snapshot carries an unexpected field "${key}"
|
|
189
|
+
findings.push(`a stateSeries snapshot carries an unexpected field "${key}": the series holds digests only, with no attribution per change`);
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
}
|
|
@@ -199,9 +199,9 @@ function participantWindows(windows) {
|
|
|
199
199
|
: []);
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
|
-
* The concurrency-on-pass gate: a
|
|
203
|
-
* overlapping in time)
|
|
204
|
-
* overlap interval
|
|
202
|
+
* The concurrency-on-pass gate: a passed concurrent run must show genuine overlap (≥2 laneWindows
|
|
203
|
+
* overlapping in time) and a stateSeries delta whose timestamp is at or after the start of an
|
|
204
|
+
* overlap interval. Otherwise it was not actually concurrent, or the world never changed under
|
|
205
205
|
* contention (a hollow concurrent claim). The facts come from concurrencyFacts, which the judge
|
|
206
206
|
* also reads.
|
|
207
207
|
*/
|
|
@@ -213,32 +213,32 @@ function concurrencyOnPassFindings(bundle, windows, stateSeries) {
|
|
|
213
213
|
: []));
|
|
214
214
|
if (!facts.overlap) {
|
|
215
215
|
return [
|
|
216
|
-
"review verdict is pass but no two laneWindows overlap in time
|
|
216
|
+
"the review verdict is pass, but no two laneWindows overlap in time, so the participants did not run at once",
|
|
217
217
|
];
|
|
218
218
|
}
|
|
219
219
|
if (facts.stateChangedUnderOverlap === true)
|
|
220
220
|
return [];
|
|
221
221
|
return [
|
|
222
|
-
"review verdict is pass but no stateSeries
|
|
222
|
+
"the review verdict is pass, but no stateSeries change happens at or after the start of an overlap, so the shared app did not change while the participants ran together",
|
|
223
223
|
];
|
|
224
224
|
}
|
|
225
225
|
/**
|
|
226
|
-
*
|
|
227
|
-
* once. The
|
|
228
|
-
*
|
|
229
|
-
* seeded), exposure is
|
|
230
|
-
* operator-attested (publicOriginDigest
|
|
226
|
+
* External-public concurrent branch: N participants drove one real operator-owned public deployment
|
|
227
|
+
* at once. The evidence class for a plane the harness does not own. Verify fails closed on the
|
|
228
|
+
* downgrades (asserted-absent, never silently dropped): provenance is "external-public" (never
|
|
229
|
+
* seeded), exposure is absent (claiming synthetic on a real site would be false), plane control is
|
|
230
|
+
* operator-attested (publicOriginDigest; there is no harness-minted hostDigest), there is no
|
|
231
231
|
* authoritative shared-state proof (stateSeries omitted), and concurrency is proven by temporal
|
|
232
|
-
* co-occupancy
|
|
232
|
+
* co-occupancy only (relaxed concurrency-on-pass: ≥2 overlapping windows, no state delta). Every
|
|
233
233
|
* getHost-only claim (exposure: synthetic / plane.hostDigest / seeded / synthetic limit) appearing
|
|
234
|
-
* here
|
|
234
|
+
* here fails closed.
|
|
235
235
|
*/
|
|
236
236
|
function externalPublicConcurrentFindings(bundle, sw) {
|
|
237
237
|
const findings = sharedWorldCommonFindings(bundle, sw);
|
|
238
|
-
// Shape coherence: concurrent carries laneWindows + outcomes
|
|
239
|
-
// deliberately
|
|
238
|
+
// Shape coherence: concurrent carries laneWindows + outcomes and no timeline. stateSeries is
|
|
239
|
+
// deliberately omitted on this class (no in-sandbox filesystem to authoritatively digest).
|
|
240
240
|
if (Array.isArray(sw.timeline)) {
|
|
241
|
-
findings.push("an external-public concurrent bundle must
|
|
241
|
+
findings.push("an external-public concurrent bundle must not carry a sequential timeline (topologyMode mismatch)");
|
|
242
242
|
}
|
|
243
243
|
const windows = recordsOf(sw.laneWindows);
|
|
244
244
|
const outcomes = recordsOf(sw.outcomes);
|
|
@@ -246,87 +246,89 @@ function externalPublicConcurrentFindings(bundle, sw) {
|
|
|
246
246
|
findings.push("an external-public concurrent bundle must carry laneWindows");
|
|
247
247
|
if (outcomes === null)
|
|
248
248
|
findings.push("an external-public concurrent bundle must carry outcomes");
|
|
249
|
-
//
|
|
249
|
+
// No authoritative shared-state proof: a non-empty stateSeries would falsely imply the harness
|
|
250
250
|
// digested the plane's backend state (it cannot; there is no in-sandbox filesystem).
|
|
251
251
|
const stateSeries = sw.stateSeries;
|
|
252
252
|
if (Array.isArray(stateSeries) && stateSeries.length > 0) {
|
|
253
|
-
findings.push("an external-public concurrent bundle must
|
|
253
|
+
findings.push("an external-public concurrent bundle must not carry a stateSeries: humanish cannot read the state of a public deployment it does not run, so this route shows concurrency by overlapping sessions instead");
|
|
254
254
|
}
|
|
255
255
|
if (windows === null || outcomes === null) {
|
|
256
256
|
return findings; // can't reason further without the core series
|
|
257
257
|
}
|
|
258
|
-
// Attribution ceiling: the concurrent family
|
|
258
|
+
// Attribution ceiling: the concurrent family and every external-public downgrade disclosure
|
|
259
259
|
// must be present; the sequential family + any seeded/synthetic limit must be absent.
|
|
260
260
|
findings.push(...attributionLimitFindings(sw, [...CONCURRENT_REQUIRED_LIMITS, ...EXTERNAL_PUBLIC_EXTRA_LIMITS], EXTERNAL_PUBLIC_FORBIDDEN_LIMITS, {
|
|
261
|
-
missing: (limit) => `attributionLimits is missing the
|
|
262
|
-
forbidden: (limit) => `attributionLimits carries the
|
|
261
|
+
missing: (limit) => `attributionLimits is missing the required external-public disclosure "${limit}"; without it the bundle claims more than the run can show`,
|
|
262
|
+
forbidden: (limit) => `attributionLimits carries the disclosure "${limit}", which an external-public run cannot claim: it describes a sequential guarantee or seeded synthetic data, and the app is a real deployment`,
|
|
263
263
|
}), ...participantCoverageFindings(sw, windows, outcomes), ...windowFindings(bundle, windows, "the origin it reached"), ...externalPublicPlaneFindings(bundle, sw, windows));
|
|
264
|
-
// The
|
|
265
|
-
// co-occupancy (≥2 laneWindows overlapping in time). There is
|
|
264
|
+
// The relaxed concurrency-on-pass gate: a passed external-public run must show genuine temporal
|
|
265
|
+
// co-occupancy (≥2 laneWindows overlapping in time). There is no state-delta requirement: the
|
|
266
266
|
// observed co-occupancy of one declared origin (plus the optional lobby convergence) carries the
|
|
267
267
|
// "they shared a world" claim, disclosed as concurrency-by-temporal-co-occupancy-only.
|
|
268
268
|
if (bundle.review.verdict === "pass" &&
|
|
269
269
|
!concurrencyFacts(participantWindows(windows), undefined).overlap) {
|
|
270
|
-
findings.push("review verdict is pass but no two laneWindows overlap in time
|
|
270
|
+
findings.push("the review verdict is pass, but no two laneWindows overlap in time, so the participants of this external-public run did not run at once");
|
|
271
271
|
}
|
|
272
272
|
return findings;
|
|
273
273
|
}
|
|
274
274
|
/**
|
|
275
|
-
* The external-public plane (the
|
|
276
|
-
* converged on one
|
|
277
|
-
* and every laneWindow shares the plane's provenance.
|
|
275
|
+
* The external-public plane (the counterpart of the harness-minted-URL rule, with a weaker,
|
|
276
|
+
* disclosed claim): the participants converged on one observed origin, nothing claims harness
|
|
277
|
+
* control or a synthetic seeded subject, and every laneWindow shares the plane's provenance.
|
|
278
278
|
*/
|
|
279
279
|
function externalPublicPlaneFindings(bundle, sw, windows) {
|
|
280
280
|
const findings = [];
|
|
281
|
-
// The convergence proof is about what the
|
|
282
|
-
// plane.publicOriginDigest is the
|
|
283
|
-
//
|
|
284
|
-
// origin. Convergence on one observed origin proves
|
|
285
|
-
// of the plane.
|
|
286
|
-
// attestation + the declared appUrl
|
|
287
|
-
// (apex->www, http->https) makes the observed origin
|
|
288
|
-
// expected and must
|
|
281
|
+
// The convergence proof is about what the participants observed; the declared origin is not part
|
|
282
|
+
// of it. plane.publicOriginDigest is the observed origin the participants converged on; verify
|
|
283
|
+
// requires every participant's CDP-observed routeHostDigest to agree on one origin, and that
|
|
284
|
+
// publicOriginDigest be that origin. Convergence on one observed origin proves cross-participant
|
|
285
|
+
// co-location. It does not prove harness control of the plane. Operator ownership rests on the
|
|
286
|
+
// subject.publicTarget.authorized attestation + the declared appUrl. Digest equality plays no
|
|
287
|
+
// part, because a normal cross-origin redirect (apex->www, http->https) makes the observed origin
|
|
288
|
+
// differ from the declared one, which is expected and must never fail verify
|
|
289
|
+
// (declaredOriginDigest is evidence-only).
|
|
289
290
|
const plane = isRecord(sw.plane) ? sw.plane : {};
|
|
290
291
|
const publicOriginDigest = typeof plane.publicOriginDigest === "string" ? plane.publicOriginDigest : undefined;
|
|
291
292
|
if (!publicOriginDigest || !COMMAND_DIGEST_PATTERN.test(publicOriginDigest)) {
|
|
292
|
-
findings.push("sharedWorld.plane.publicOriginDigest (sha256-16 of the
|
|
293
|
+
findings.push("sharedWorld.plane.publicOriginDigest (the sha256-16 of the origin the participants were observed to reach) is required on an external-public run");
|
|
293
294
|
}
|
|
294
|
-
// The observed origins across
|
|
295
|
+
// The observed origins across participants must agree on exactly one (that agreement is the
|
|
296
|
+
// convergence).
|
|
295
297
|
const observedOrigins = windows
|
|
296
298
|
.map((window) => typeof window.routeHostDigest === "string" ? window.routeHostDigest : undefined)
|
|
297
299
|
.filter((digest) => digest !== undefined);
|
|
298
300
|
const distinctObserved = [...new Set(observedOrigins)];
|
|
299
301
|
if (distinctObserved.length > 1) {
|
|
300
|
-
findings.push(`the participants
|
|
302
|
+
findings.push(`the participants were observed on more than one origin; observed origin digests: ${distinctObserved.join(", ")}`);
|
|
301
303
|
}
|
|
302
304
|
else if (publicOriginDigest &&
|
|
303
305
|
distinctObserved.length === 1 &&
|
|
304
306
|
distinctObserved[0] !== publicOriginDigest) {
|
|
305
|
-
findings.push(`sharedWorld.plane.publicOriginDigest (${publicOriginDigest}) must equal the
|
|
307
|
+
findings.push(`sharedWorld.plane.publicOriginDigest (${publicOriginDigest}) must equal the one origin the participants were observed to reach (${distinctObserved[0]})`);
|
|
306
308
|
}
|
|
307
|
-
// declaredOriginDigest is recorded for evidence
|
|
308
|
-
// assert it equals the observed origin
|
|
309
|
+
// declaredOriginDigest is recorded for evidence only. Validate its shape when present, but never
|
|
310
|
+
// assert it equals the observed origin: a cross-origin redirect is normal and expected.
|
|
309
311
|
if (plane.declaredOriginDigest !== undefined &&
|
|
310
312
|
(typeof plane.declaredOriginDigest !== "string" ||
|
|
311
313
|
!COMMAND_DIGEST_PATTERN.test(plane.declaredOriginDigest))) {
|
|
312
314
|
findings.push("sharedWorld.plane.declaredOriginDigest, when present, must be a sha256-16 digest of the operator-declared origin (evidence-only; not asserted equal to the observed origin)");
|
|
313
315
|
}
|
|
314
|
-
//
|
|
315
|
-
// the harness-minted hostDigest
|
|
316
|
+
// Invert the getHost gate: exposure must be absent (claiming synthetic on a real site would be false) and
|
|
317
|
+
// the harness-minted hostDigest must be absent (the harness minted no host here).
|
|
316
318
|
if (plane.exposure !== undefined) {
|
|
317
|
-
findings.push('sharedWorld.plane.exposure must be
|
|
319
|
+
findings.push('sharedWorld.plane.exposure must be absent on an external-public run: humanish did not provision the app, so it cannot declare a real deployment "synthetic"');
|
|
318
320
|
}
|
|
319
321
|
if (plane.hostDigest !== undefined) {
|
|
320
|
-
findings.push("sharedWorld.plane.hostDigest must be
|
|
322
|
+
findings.push("sharedWorld.plane.hostDigest must be absent on an external-public run: it records a sandbox URL humanish created, and this app is a deployment the operator declared");
|
|
321
323
|
}
|
|
322
|
-
// Provenance is the external-public marker
|
|
324
|
+
// Provenance is the external-public marker, which is neither seeded (nothing was seeded) nor unpinned.
|
|
323
325
|
if (bundle.subject?.state.provenance !== "external-public") {
|
|
324
|
-
findings.push(`
|
|
326
|
+
findings.push(`an external-public run needs subject.state.provenance == "external-public" (got "${bundle.subject?.state.provenance ?? "absent"}"): seeded, unpinned or undeclared does not describe a public deployment the operator runs`);
|
|
325
327
|
}
|
|
326
328
|
if (bundle.subject?.source !== "app-url") {
|
|
327
|
-
findings.push('
|
|
329
|
+
findings.push('an external-public run needs subject.source == "app-url": the app is a public deployment, not a subject humanish provisions');
|
|
328
330
|
}
|
|
329
|
-
// Single-plane provenance: every laneWindow shares
|
|
331
|
+
// Single-plane provenance: every laneWindow shares one (commit, seedDigest) matching plane. commit
|
|
330
332
|
// is absent on this class (nothing cloned); seedDigest is the constant empty-recipe digest.
|
|
331
333
|
findings.push(...planeProvenanceFindings(windows, plane, {
|
|
332
334
|
items: "laneWindows",
|
|
@@ -334,7 +336,8 @@ function externalPublicPlaneFindings(bundle, sw, windows) {
|
|
|
334
336
|
run: "shared-world",
|
|
335
337
|
}));
|
|
336
338
|
// The lobby-convergence proof (optional-but-strong): if present it must be a sha256-16 digest of the
|
|
337
|
-
// shared
|
|
339
|
+
// shared `/lobby/CODE` path all participants converged on (digest-only; the raw lobby code never
|
|
340
|
+
// lands).
|
|
338
341
|
const lobbyConvergenceDigest = sw
|
|
339
342
|
.lobbyConvergenceDigest;
|
|
340
343
|
if (lobbyConvergenceDigest !== undefined &&
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RunBundle } from "../run/bundle.js";
|
|
2
2
|
/**
|
|
3
|
-
* The `shared-world evidence` check
|
|
4
|
-
* interaction
|
|
3
|
+
* The `shared-world evidence` check: a live shared-world bundle's
|
|
4
|
+
* interaction claim must match its recorded timeline + plane provenance, and its attribution
|
|
5
5
|
* ceiling must be pinned. Mirrors validateTerminalProductEvidence: live-only (dry-run contract
|
|
6
6
|
* bundles are skipped, exactly like the other live-only checks). Fail-closed on every overclaim.
|
|
7
7
|
*/
|
|
@@ -2,8 +2,8 @@ import { COMMAND_DIGEST_PATTERN, MANDATORY_ATTRIBUTION_LIMITS, SHARED_WORLD_CHEC
|
|
|
2
2
|
import { isRecord } from "../run/type-guards.js";
|
|
3
3
|
import { concurrentSharedWorldFindings } from "./shared-world-concurrent.js";
|
|
4
4
|
/**
|
|
5
|
-
* The `shared-world evidence` check
|
|
6
|
-
* interaction
|
|
5
|
+
* The `shared-world evidence` check: a live shared-world bundle's
|
|
6
|
+
* interaction claim must match its recorded timeline + plane provenance, and its attribution
|
|
7
7
|
* ceiling must be pinned. Mirrors validateTerminalProductEvidence: live-only (dry-run contract
|
|
8
8
|
* bundles are skipped, exactly like the other live-only checks). Fail-closed on every overclaim.
|
|
9
9
|
*/
|
|
@@ -15,13 +15,13 @@ export function sharedWorldEvidenceFindings(bundle) {
|
|
|
15
15
|
}
|
|
16
16
|
const sw = bundle.sharedWorld;
|
|
17
17
|
if (!sw) {
|
|
18
|
-
// A live bundle that
|
|
19
|
-
// hollow claim
|
|
18
|
+
// A live bundle that declares shared-world attribution but carries no evidence block is a
|
|
19
|
+
// hollow claim, so it fails closed. (Absent attributionClass + absent block == an ordinary bundle.)
|
|
20
20
|
return bundle.attributionClass === "shared-world"
|
|
21
21
|
? ["attributionClass is shared-world but the sharedWorld evidence block is missing"]
|
|
22
22
|
: [];
|
|
23
23
|
}
|
|
24
|
-
// Dispatch on topologyMode
|
|
24
|
+
// Dispatch on topologyMode first; unknown/missing → fail closed.
|
|
25
25
|
const topologyMode = sw.topologyMode;
|
|
26
26
|
if (topologyMode !== "sequential" && sw.skippedTail !== undefined) {
|
|
27
27
|
return ["skippedTail is only valid on sequential shared-world evidence"];
|
|
@@ -33,7 +33,7 @@ export function sharedWorldEvidenceFindings(bundle) {
|
|
|
33
33
|
return concurrentSharedWorldFindings(bundle, sw);
|
|
34
34
|
}
|
|
35
35
|
return [
|
|
36
|
-
'sharedWorld.topologyMode must be "sequential" or "concurrent"
|
|
36
|
+
'sharedWorld.topologyMode must be "sequential" or "concurrent"; a missing or unknown value fails verification',
|
|
37
37
|
];
|
|
38
38
|
}
|
|
39
39
|
/** Validate the declared suffix against the executed prefix and existing participant evidence. */
|
|
@@ -186,8 +186,8 @@ function runSpendLimitRecorded(bundle, turns, tail) {
|
|
|
186
186
|
sum > tail.maxTotalUsd);
|
|
187
187
|
}
|
|
188
188
|
/**
|
|
189
|
-
*
|
|
190
|
-
* carry the sequential attributionLimits. A sequential bundle must
|
|
189
|
+
* Sequential branch: the alternating timeline must be well-formed, single-plane, digest-only, and
|
|
190
|
+
* carry the sequential attributionLimits. A sequential bundle must not carry concurrent fields
|
|
191
191
|
* (laneWindows).
|
|
192
192
|
*/
|
|
193
193
|
function sequentialSharedWorldFindings(bundle, sw) {
|
|
@@ -201,14 +201,14 @@ function sequentialSharedWorldFindings(bundle, sw) {
|
|
|
201
201
|
findings.push("a sequential shared-world bundle must carry a timeline");
|
|
202
202
|
}
|
|
203
203
|
if (Array.isArray(sw.laneWindows)) {
|
|
204
|
-
findings.push("a sequential shared-world bundle must
|
|
204
|
+
findings.push("a sequential shared-world bundle must not carry concurrent laneWindows (topologyMode mismatch)");
|
|
205
205
|
}
|
|
206
206
|
const sequence = Array.isArray(sw.sequence) ? sw.sequence : [];
|
|
207
|
-
// Attribution ceiling: every mandatory limit
|
|
207
|
+
// Attribution ceiling: every mandatory limit must be present (omission overclaims → fail).
|
|
208
208
|
const limits = Array.isArray(sw.attributionLimits) ? sw.attributionLimits : [];
|
|
209
209
|
for (const required of MANDATORY_ATTRIBUTION_LIMITS) {
|
|
210
210
|
if (!limits.includes(required)) {
|
|
211
|
-
findings.push(`attributionLimits is missing the
|
|
211
|
+
findings.push(`attributionLimits is missing the required disclosure "${required}"; without it the bundle claims more than the run can show`);
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
const checkpoints = rawTimeline.filter((entry) => isRecord(entry) && entry.kind === "checkpoint");
|
|
@@ -256,7 +256,7 @@ function sequentialSharedWorldFindings(bundle, sw) {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
});
|
|
259
|
-
// Checkpoints: digest is sha256-16 and the record carries
|
|
259
|
+
// Checkpoints: digest is sha256-16 and the record carries no value-shaped field (digest-only).
|
|
260
260
|
for (const checkpoint of checkpoints) {
|
|
261
261
|
const name = typeof checkpoint.name === "string" ? checkpoint.name : "(unnamed)";
|
|
262
262
|
if (typeof checkpoint.digest !== "string" || !COMMAND_DIGEST_PATTERN.test(checkpoint.digest)) {
|
|
@@ -264,7 +264,7 @@ function sequentialSharedWorldFindings(bundle, sw) {
|
|
|
264
264
|
}
|
|
265
265
|
for (const key of Object.keys(checkpoint)) {
|
|
266
266
|
if (!SHARED_WORLD_CHECKPOINT_KEYS.has(key)) {
|
|
267
|
-
findings.push(`checkpoint "${name}" carries an unexpected field "${key}"
|
|
267
|
+
findings.push(`checkpoint "${name}" carries an unexpected field "${key}": checkpoints store digests only`);
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
}
|
|
@@ -278,18 +278,18 @@ function sequentialSharedWorldFindings(bundle, sw) {
|
|
|
278
278
|
findings.push(`turn "${participantId}" references unknown streamId "${String(turn.streamId)}"`);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
-
// Single-plane provenance: every turn shares
|
|
281
|
+
// Single-plane provenance: every turn shares one (commit, seedDigest), matching sharedWorld.plane.
|
|
282
282
|
// (plane.seedDigest + plane.envNames shape are checked in sharedWorldCommonFindings.)
|
|
283
283
|
findings.push(...planeProvenanceFindings(turns, sw.plane, {
|
|
284
284
|
items: "turns",
|
|
285
285
|
item: "turn",
|
|
286
286
|
run: "shared-world",
|
|
287
287
|
}));
|
|
288
|
-
// The delta-on-pass gate: a
|
|
288
|
+
// The delta-on-pass gate: a passed shared-world run must show at least one checkpoint delta;
|
|
289
289
|
// otherwise the roles never interacted through shared state and the claim is hollow.
|
|
290
290
|
if (bundle.review.verdict === "pass" &&
|
|
291
291
|
!checkpoints.some((checkpoint) => checkpoint.deltaFromPrev === true)) {
|
|
292
|
-
findings.push("review verdict is pass but no checkpoint shows deltaFromPrev
|
|
292
|
+
findings.push("the review verdict is pass, but no checkpoint shows deltaFromPrev, so no change to the shared app was observed");
|
|
293
293
|
}
|
|
294
294
|
return findings;
|
|
295
295
|
}
|
package/dist/verify/subject.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RunBundle } from "../run/bundle.js";
|
|
2
2
|
/**
|
|
3
|
-
* The `subject state provenance` check
|
|
3
|
+
* The `subject state provenance` check: a bundle's subject claim
|
|
4
4
|
* must match its recorded evidence. A bundle without a subject block passes untouched.
|
|
5
5
|
* Live-vs-dry-run is judged from bundle.mode, exactly like
|
|
6
6
|
* noEngagementActorFindings. Covers both the state story (seed/external) and, for the
|
|
@@ -8,10 +8,10 @@ import type { RunBundle } from "../run/bundle.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function subjectStateFindings(bundle: RunBundle): string[];
|
|
10
10
|
/**
|
|
11
|
-
* Advisory (never flips ok): a
|
|
11
|
+
* Advisory (never flips ok): a live clone bundle whose subject env is provisioned while its
|
|
12
12
|
* state story is undeclared probably points at state the lab does not control. Emitted at
|
|
13
|
-
* most
|
|
14
|
-
* is mechanically excluded: the harness consumes that name for clone auth
|
|
13
|
+
* most once per bundle (the subject block is bundle-level, never per stream). GITHUB_TOKEN
|
|
14
|
+
* is mechanically excluded: the harness consumes that name for clone auth, and it carries no
|
|
15
15
|
* state implication.
|
|
16
16
|
*/
|
|
17
17
|
export declare function undeclaredSubjectStateWarnings(bundle: RunBundle): string[];
|
package/dist/verify/subject.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { COMMAND_DIGEST_PATTERN, SUBJECT_ENV_NAME_PATTERN } from "../run/shared-world-shape.js";
|
|
4
4
|
import { ARCHIVE_SHA256_PATTERN } from "../run/bundle-shape.js";
|
|
5
5
|
/**
|
|
6
|
-
* The `subject state provenance` check
|
|
6
|
+
* The `subject state provenance` check: a bundle's subject claim
|
|
7
7
|
* must match its recorded evidence. A bundle without a subject block passes untouched.
|
|
8
8
|
* Live-vs-dry-run is judged from bundle.mode, exactly like
|
|
9
9
|
* noEngagementActorFindings. Covers both the state story (seed/external) and, for the
|
|
@@ -18,34 +18,34 @@ export function subjectStateFindings(bundle) {
|
|
|
18
18
|
const state = subject.state;
|
|
19
19
|
const seed = state.seed ?? [];
|
|
20
20
|
const live = bundle.mode === "live";
|
|
21
|
-
// Local-tree fail-closed pin: a
|
|
22
|
-
// digest
|
|
21
|
+
// Local-tree fail-closed pin: a live local-tree subject must carry a well-formed archive
|
|
22
|
+
// digest: a dirty tree cannot be commit-pinned, so archiveSha256 is the only content pin
|
|
23
23
|
// this route has. Mirrors the seeded-on-dry-run discriminator immediately below: judged by
|
|
24
24
|
// bundle.mode, never by the presence/shape of other fields. Never echoes the malformed value
|
|
25
25
|
// (it could itself be a leaked value, same discipline as the externalEnvNames check below).
|
|
26
26
|
if (live && subject.source === "local-tree") {
|
|
27
27
|
// Note: a malformed-but-present string is already rejected upstream by the
|
|
28
28
|
// isRunSubjectProvenance shape gate, so in practice this branch fires for the
|
|
29
|
-
//
|
|
29
|
+
// missing case; the pattern re-check stays as defense in depth for callers
|
|
30
30
|
// that bypass the schema gate.
|
|
31
31
|
const pin = subject.archiveSha256;
|
|
32
32
|
if (typeof pin !== "string" || !ARCHIVE_SHA256_PATTERN.test(pin)) {
|
|
33
33
|
findings.push("subject.source is local-tree on a live run but archiveSha256 is missing or malformed (a local-tree subject must carry a well-formed 64-hex archive digest)");
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
// Marker-independent rule: a passed
|
|
37
|
-
// complete ok (closes the hollow-seeded × unpinned hole
|
|
36
|
+
// Marker-independent rule: a passed live run can never ride on a seed step that did not
|
|
37
|
+
// complete ok (closes the hollow-seeded × unpinned hole: an unpinned bundle still carries
|
|
38
38
|
// its seed records, and a failed migration must not hide behind the external marker).
|
|
39
39
|
if (live && bundle.review.verdict === "pass" && seed.some((record) => record.ok !== true)) {
|
|
40
|
-
findings.push("review verdict is pass but a recorded seed step did not complete
|
|
40
|
+
findings.push("the review verdict is pass, but a recorded seed step did not complete; a passed live run cannot have failed or skipped state steps");
|
|
41
41
|
}
|
|
42
42
|
switch (state.provenance) {
|
|
43
43
|
case "seeded": {
|
|
44
44
|
if (!live) {
|
|
45
|
-
findings.push('state marker "seeded" on a dry-run bundle
|
|
45
|
+
findings.push('state marker "seeded" on a dry-run bundle: a dry run executes no state steps');
|
|
46
46
|
}
|
|
47
47
|
if (seed.length === 0) {
|
|
48
|
-
findings.push('state marker "seeded" with
|
|
48
|
+
findings.push('state marker "seeded" with no seed step records claims state the run did not set up');
|
|
49
49
|
}
|
|
50
50
|
for (const record of seed) {
|
|
51
51
|
if (!COMMAND_DIGEST_PATTERN.test(record.commandDigest)) {
|
|
@@ -64,8 +64,8 @@ export function subjectStateFindings(bundle) {
|
|
|
64
64
|
}
|
|
65
65
|
for (const name of externalEnvNames) {
|
|
66
66
|
if (!SUBJECT_ENV_NAME_PATTERN.test(name)) {
|
|
67
|
-
// Deliberately does
|
|
68
|
-
findings.push("externalEnvNames
|
|
67
|
+
// Deliberately does not echo the entry: a malformed entry may be a value.
|
|
68
|
+
findings.push("externalEnvNames has an entry that is not an environment variable name; evidence may hold names only, never values");
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
break;
|
|
@@ -83,13 +83,13 @@ export function subjectStateFindings(bundle) {
|
|
|
83
83
|
// nor seeded. It has no in-sandbox state story, so a seed record or an external channel here
|
|
84
84
|
// contradicts the "no subject sandbox" invariant of this plane class.
|
|
85
85
|
if (subject.source !== "app-url") {
|
|
86
|
-
findings.push('state marker "external-public"
|
|
86
|
+
findings.push('state marker "external-public" needs subject.source "app-url": an external-public app is a public deployment, not a clone or local-tree subject');
|
|
87
87
|
}
|
|
88
88
|
if (seed.length > 0) {
|
|
89
|
-
findings.push('state marker "external-public" cannot carry seed step records
|
|
89
|
+
findings.push('state marker "external-public" cannot carry seed step records: humanish neither provisions nor seeds a public deployment');
|
|
90
90
|
}
|
|
91
91
|
if ((state.externalEnvNames ?? []).length > 0) {
|
|
92
|
-
findings.push('state marker "external-public" cannot carry externalEnvNames
|
|
92
|
+
findings.push('state marker "external-public" cannot carry externalEnvNames: the operator runs this app, so there is no external state to declare');
|
|
93
93
|
}
|
|
94
94
|
break;
|
|
95
95
|
}
|
|
@@ -99,10 +99,10 @@ export function subjectStateFindings(bundle) {
|
|
|
99
99
|
return findings;
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
|
-
* Advisory (never flips ok): a
|
|
102
|
+
* Advisory (never flips ok): a live clone bundle whose subject env is provisioned while its
|
|
103
103
|
* state story is undeclared probably points at state the lab does not control. Emitted at
|
|
104
|
-
* most
|
|
105
|
-
* is mechanically excluded: the harness consumes that name for clone auth
|
|
104
|
+
* most once per bundle (the subject block is bundle-level, never per stream). GITHUB_TOKEN
|
|
105
|
+
* is mechanically excluded: the harness consumes that name for clone auth, and it carries no
|
|
106
106
|
* state implication.
|
|
107
107
|
*/
|
|
108
108
|
export function undeclaredSubjectStateWarnings(bundle) {
|
|
@@ -118,6 +118,6 @@ export function undeclaredSubjectStateWarnings(bundle) {
|
|
|
118
118
|
return [];
|
|
119
119
|
}
|
|
120
120
|
return [
|
|
121
|
-
`Subject env is provisioned (${stateRelevantEnvNames.join(", ")}) but no state
|
|
121
|
+
`Subject env is provisioned (${stateRelevantEnvNames.join(", ")}) but no state is declared. If a name points at external state, declare it in subject.state.external (recorded as unpinned), or seed the state in the sandbox with subject.state.seed.`,
|
|
122
122
|
];
|
|
123
123
|
}
|