@piagent/platform 1.6.1 → 1.7.1
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/CHANGELOG.md +55 -0
- package/README.md +8 -2
- package/README.vi.md +11 -2
- package/adapters/common/assurance-producers.json +109 -0
- package/adapters/common/structured-assurance-facts.mjs +153 -0
- package/adapters/node-typescript/contract-families.json +2811 -0
- package/adapters/node-typescript/contract-families.md +90 -0
- package/benchmarks/production-v1/grade.mjs +20 -0
- package/benchmarks/production-v1/spend-control.v1.json +3 -3
- package/benchmarks/production-v2/grade.mjs +892 -0
- package/benchmarks/production-v2/project/README.md +7 -0
- package/benchmarks/production-v2/project/config/service.json +4 -0
- package/benchmarks/production-v2/project/data/audit-ledger.jsonl +1 -0
- package/benchmarks/production-v2/project/docs/ops.md +3 -0
- package/benchmarks/production-v2/project/logs/incident.log +2 -0
- package/benchmarks/production-v2/project/package.json +11 -0
- package/benchmarks/production-v2/project/scripts/check.mjs +21 -0
- package/benchmarks/production-v2/project/src/backend/auth.js +3 -0
- package/benchmarks/production-v2/project/src/backend/billing-window.js +4 -0
- package/benchmarks/production-v2/project/src/backend/cache.js +15 -0
- package/benchmarks/production-v2/project/src/backend/invoice.js +4 -0
- package/benchmarks/production-v2/project/src/backend/revocation-cache.js +3 -0
- package/benchmarks/production-v2/project/src/data/csv.js +3 -0
- package/benchmarks/production-v2/project/src/data/dedup.js +5 -0
- package/benchmarks/production-v2/project/src/data/migration.js +9 -0
- package/benchmarks/production-v2/project/src/data/ndjson-stream.js +5 -0
- package/benchmarks/production-v2/project/src/data/versioned-replay.js +8 -0
- package/benchmarks/production-v2/project/src/frontend/chat-events.js +7 -0
- package/benchmarks/production-v2/project/src/frontend/pagination.js +8 -0
- package/benchmarks/production-v2/project/src/frontend/request-lifecycle.js +15 -0
- package/benchmarks/production-v2/project/src/frontend/search-state.js +8 -0
- package/benchmarks/production-v2/project/src/frontend/unicode-search.js +7 -0
- package/benchmarks/production-v2/project/src/fullstack/contract-sync.js +10 -0
- package/benchmarks/production-v2/project/src/platform/args.js +10 -0
- package/benchmarks/production-v2/project/src/platform/config.js +7 -0
- package/benchmarks/production-v2/project/src/platform/workflow-session.js +9 -0
- package/benchmarks/production-v2/project/src/platform/workspace.js +13 -0
- package/benchmarks/production-v2/project/src/reliability/checkpoint.js +5 -0
- package/benchmarks/production-v2/project/src/reliability/expiry.js +5 -0
- package/benchmarks/production-v2/project/src/reliability/retry.js +15 -0
- package/benchmarks/production-v2/project/test/smoke.test.js +21 -0
- package/benchmarks/production-v2/project/vendor/README.md +1 -0
- package/benchmarks/production-v2/prompts/abort-reconnect-supersession.md +11 -0
- package/benchmarks/production-v2/prompts/backend-frontend-contract-sync.md +12 -0
- package/benchmarks/production-v2/prompts/billing-cutoff-clock-skew.md +11 -0
- package/benchmarks/production-v2/prompts/bounded-retry.md +7 -0
- package/benchmarks/production-v2/prompts/chunked-record-boundary.md +9 -0
- package/benchmarks/production-v2/prompts/cli-double-dash.md +7 -0
- package/benchmarks/production-v2/prompts/config-precedence.md +6 -0
- package/benchmarks/production-v2/prompts/destructive-history-refusal.md +3 -0
- package/benchmarks/production-v2/prompts/expiry-boundary.md +7 -0
- package/benchmarks/production-v2/prompts/idempotent-replay-conflict.md +11 -0
- package/benchmarks/production-v2/prompts/incident-diagnosis.md +4 -0
- package/benchmarks/production-v2/prompts/invoice-rounding.md +9 -0
- package/benchmarks/production-v2/prompts/journeys/config-precedence-scout.md +3 -0
- package/benchmarks/production-v2/prompts/journeys/expiry-boundary-scout.md +3 -0
- package/benchmarks/production-v2/prompts/journeys/quoted-csv-scout.md +3 -0
- package/benchmarks/production-v2/prompts/journeys/recover-after-uncertain-send.md +4 -0
- package/benchmarks/production-v2/prompts/journeys/repository-prompt-injection-scout.md +4 -0
- package/benchmarks/production-v2/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
- package/benchmarks/production-v2/prompts/journeys/stable-dedup-scout.md +3 -0
- package/benchmarks/production-v2/prompts/journeys/stale-search-response-scout.md +3 -0
- package/benchmarks/production-v2/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
- package/benchmarks/production-v2/prompts/journeys/verify-current-contract.md +4 -0
- package/benchmarks/production-v2/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
- package/benchmarks/production-v2/prompts/pagination-boundary.md +7 -0
- package/benchmarks/production-v2/prompts/protected-env-refusal.md +2 -0
- package/benchmarks/production-v2/prompts/quoted-csv.md +6 -0
- package/benchmarks/production-v2/prompts/reconnect-chat-event-order.md +19 -0
- package/benchmarks/production-v2/prompts/repository-prompt-injection.md +5 -0
- package/benchmarks/production-v2/prompts/resumable-checkpoint-partial-failure.md +11 -0
- package/benchmarks/production-v2/prompts/revoked-session-cache.md +10 -0
- package/benchmarks/production-v2/prompts/schema-migration.md +6 -0
- package/benchmarks/production-v2/prompts/stable-dedup.md +6 -0
- package/benchmarks/production-v2/prompts/stale-search-response.md +6 -0
- package/benchmarks/production-v2/prompts/tenant-cache-isolation.md +6 -0
- package/benchmarks/production-v2/prompts/tenant-role-authorization.md +6 -0
- package/benchmarks/production-v2/prompts/unicode-search.md +6 -0
- package/benchmarks/production-v2/prompts/workflow-switch-same-session.md +30 -0
- package/benchmarks/production-v2/prompts/workspace-order.md +7 -0
- package/benchmarks/production-v2/spend-control.v1.json +115 -0
- package/benchmarks/production-v2/suite.json +1009 -0
- package/benchmarks/production-v2/variant.mjs +169 -0
- package/benchmarks/production-v3/CONTRACT-REVISION-20260922.md +31 -0
- package/benchmarks/production-v3/calibration/corpus.v1.json +63 -0
- package/benchmarks/production-v3/calibration/human-review-rubric.v1.json +36 -0
- package/benchmarks/production-v3/grade.mjs +1017 -0
- package/benchmarks/production-v3/project/README.md +7 -0
- package/benchmarks/production-v3/project/config/service.json +4 -0
- package/benchmarks/production-v3/project/data/audit-ledger.jsonl +1 -0
- package/benchmarks/production-v3/project/docs/ops.md +3 -0
- package/benchmarks/production-v3/project/logs/incident.log +2 -0
- package/benchmarks/production-v3/project/package.json +11 -0
- package/benchmarks/production-v3/project/scripts/check.mjs +21 -0
- package/benchmarks/production-v3/project/src/backend/auth.js +3 -0
- package/benchmarks/production-v3/project/src/backend/billing-window.js +4 -0
- package/benchmarks/production-v3/project/src/backend/cache.js +15 -0
- package/benchmarks/production-v3/project/src/backend/invoice.js +4 -0
- package/benchmarks/production-v3/project/src/backend/revocation-cache.js +12 -0
- package/benchmarks/production-v3/project/src/data/csv.js +3 -0
- package/benchmarks/production-v3/project/src/data/dedup.js +5 -0
- package/benchmarks/production-v3/project/src/data/migration.js +9 -0
- package/benchmarks/production-v3/project/src/data/ndjson-stream.js +5 -0
- package/benchmarks/production-v3/project/src/data/versioned-replay.js +8 -0
- package/benchmarks/production-v3/project/src/frontend/chat-events.js +7 -0
- package/benchmarks/production-v3/project/src/frontend/pagination.js +8 -0
- package/benchmarks/production-v3/project/src/frontend/request-lifecycle.js +23 -0
- package/benchmarks/production-v3/project/src/frontend/search-state.js +8 -0
- package/benchmarks/production-v3/project/src/frontend/unicode-search.js +7 -0
- package/benchmarks/production-v3/project/src/fullstack/contract-sync.js +10 -0
- package/benchmarks/production-v3/project/src/platform/args.js +10 -0
- package/benchmarks/production-v3/project/src/platform/config.js +7 -0
- package/benchmarks/production-v3/project/src/platform/workflow-session.js +9 -0
- package/benchmarks/production-v3/project/src/platform/workspace.js +13 -0
- package/benchmarks/production-v3/project/src/reliability/checkpoint.js +5 -0
- package/benchmarks/production-v3/project/src/reliability/expiry.js +14 -0
- package/benchmarks/production-v3/project/src/reliability/retry.js +15 -0
- package/benchmarks/production-v3/project/test/smoke.test.js +21 -0
- package/benchmarks/production-v3/project/vendor/README.md +1 -0
- package/benchmarks/production-v3/prompts/abort-reconnect-supersession.md +11 -0
- package/benchmarks/production-v3/prompts/backend-frontend-contract-sync.md +20 -0
- package/benchmarks/production-v3/prompts/billing-cutoff-clock-skew.md +11 -0
- package/benchmarks/production-v3/prompts/bounded-retry.md +7 -0
- package/benchmarks/production-v3/prompts/chunked-record-boundary.md +11 -0
- package/benchmarks/production-v3/prompts/cli-double-dash.md +7 -0
- package/benchmarks/production-v3/prompts/config-precedence.md +6 -0
- package/benchmarks/production-v3/prompts/destructive-history-refusal.md +9 -0
- package/benchmarks/production-v3/prompts/expiry-boundary.md +14 -0
- package/benchmarks/production-v3/prompts/idempotent-replay-conflict.md +13 -0
- package/benchmarks/production-v3/prompts/incident-diagnosis.md +4 -0
- package/benchmarks/production-v3/prompts/invoice-rounding.md +9 -0
- package/benchmarks/production-v3/prompts/journeys/config-precedence-scout.md +3 -0
- package/benchmarks/production-v3/prompts/journeys/expiry-boundary-scout.md +3 -0
- package/benchmarks/production-v3/prompts/journeys/quoted-csv-scout.md +3 -0
- package/benchmarks/production-v3/prompts/journeys/recover-after-uncertain-send.md +4 -0
- package/benchmarks/production-v3/prompts/journeys/repository-prompt-injection-scout.md +4 -0
- package/benchmarks/production-v3/prompts/journeys/resumable-checkpoint-partial-failure-scout.md +4 -0
- package/benchmarks/production-v3/prompts/journeys/stable-dedup-scout.md +3 -0
- package/benchmarks/production-v3/prompts/journeys/stale-search-response-scout.md +3 -0
- package/benchmarks/production-v3/prompts/journeys/tenant-cache-isolation-scout.md +4 -0
- package/benchmarks/production-v3/prompts/journeys/verify-current-contract.md +4 -0
- package/benchmarks/production-v3/prompts/journeys/workflow-switch-same-session-scout.md +4 -0
- package/benchmarks/production-v3/prompts/pagination-boundary.md +9 -0
- package/benchmarks/production-v3/prompts/protected-env-refusal.md +8 -0
- package/benchmarks/production-v3/prompts/quoted-csv.md +6 -0
- package/benchmarks/production-v3/prompts/reconnect-chat-event-order.md +20 -0
- package/benchmarks/production-v3/prompts/repository-prompt-injection.md +5 -0
- package/benchmarks/production-v3/prompts/resumable-checkpoint-partial-failure.md +15 -0
- package/benchmarks/production-v3/prompts/revoked-session-cache.md +10 -0
- package/benchmarks/production-v3/prompts/schema-migration.md +6 -0
- package/benchmarks/production-v3/prompts/stable-dedup.md +6 -0
- package/benchmarks/production-v3/prompts/stale-search-response.md +6 -0
- package/benchmarks/production-v3/prompts/tenant-cache-isolation.md +6 -0
- package/benchmarks/production-v3/prompts/tenant-role-authorization.md +6 -0
- package/benchmarks/production-v3/prompts/unicode-search.md +6 -0
- package/benchmarks/production-v3/prompts/workflow-switch-same-session.md +30 -0
- package/benchmarks/production-v3/prompts/workspace-order.md +7 -0
- package/benchmarks/production-v3/public-checks/abort-reconnect-supersession.js +34 -0
- package/benchmarks/production-v3/public-checks/expiry-boundary.js +29 -0
- package/benchmarks/production-v3/public-checks/revoked-session-cache.js +20 -0
- package/benchmarks/production-v3/spend-control.v1.json +121 -0
- package/benchmarks/production-v3/suite.json +1010 -0
- package/benchmarks/production-v3/variant.mjs +178 -0
- package/catalog/capabilities.json +2 -2
- package/docs/benchmark-codex-mcp-metadata-contract-v1.md +159 -0
- package/docs/benchmark-codex-mcp-metadata-contract-v2.md +182 -0
- package/docs/benchmark-codex-mcp-metadata-contract-v3.md +194 -0
- package/docs/benchmark-public-contract-addendum-v2.md +85 -0
- package/docs/benchmark-public-contract-addendum-v3.md +116 -0
- package/docs/command-reference-vietnamese.md +10 -7
- package/docs/context-window-policy.md +3 -3
- package/docs/distribution-standard.md +9 -9
- package/docs/languages.json +2 -2
- package/docs/operator-manual-vietnamese.md +12 -12
- package/docs/piagent-codex-benchmark-recovery-plan.md +1817 -0
- package/docs/piagent-core-evaluation-specs-2026-09-06.json +706 -0
- package/docs/piagent-core-improvement-plan.md +528 -0
- package/docs/piagent-core-offline-implementation-2026-09-06.md +219 -0
- package/docs/piagent-core-plan-checkpoint-2026-09-06.json +69 -0
- package/docs/piagent-core-reasoning-research-2026-09-06.md +225 -0
- package/docs/piagent-core-research-sources-2026-09-06.json +416 -0
- package/docs/piagent-open-session-wait.md +19 -0
- package/docs/piagent-runtime-benchmark-execution-plan.md +685 -0
- package/docs/publishing-for-teams.md +2 -0
- package/docs/quality-benchmark.md +128 -8
- package/docs/quickstart-vietnamese.md +2 -2
- package/docs/release-install-policy.md +32 -9
- package/docs/research/harness-next-evidence-review.md +113 -0
- package/docs/team-onboarding.md +7 -7
- package/docs/third-party-neutrality.md +7 -0
- package/docs/usage-observability.md +1 -1
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/en/runtime.html +1 -1
- package/docs-site/content/en/whats-new.html +11 -0
- package/docs-site/content/runtime.html +2 -2
- package/docs-site/content/whats-new.html +11 -0
- package/docs-site/context-engine.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/index.html +1 -1
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +2 -2
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +12 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +1 -1
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +3 -3
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +12 -1
- package/docs-site/workflows.html +1 -1
- package/evals/architecture-conformance-v1/lane.json +18 -0
- package/evals/architecture-conformance-v1/runner.mjs +77 -0
- package/evals/fixtures/approved-host-contracts.invalid.json +43 -0
- package/evals/fixtures/approved-host-contracts.valid.json +43 -0
- package/evals/fixtures/benchmark-attempt-outcome.invalid.json +42 -0
- package/evals/fixtures/benchmark-attempt-outcome.valid.json +42 -0
- package/evals/fixtures/benchmark-independent-verification-plan.invalid.json +7 -0
- package/evals/fixtures/benchmark-independent-verification-plan.valid.json +21 -0
- package/evals/fixtures/composite-criterion.invalid.json +10 -0
- package/evals/fixtures/composite-criterion.valid.json +33 -0
- package/evals/fixtures/contract-family-library.invalid.json +42 -0
- package/evals/fixtures/contract-family-library.valid.json +41 -0
- package/evals/fixtures/contract-selection-recipe.invalid.json +29 -0
- package/evals/fixtures/contract-selection-recipe.valid.json +29 -0
- package/evals/fixtures/host-contract-plan.invalid.json +42 -0
- package/evals/fixtures/host-contract-plan.valid.json +41 -0
- package/evals/fixtures/scoped-project-verification-receipt-v2.invalid.json +42 -0
- package/evals/fixtures/scoped-project-verification-receipt-v2.valid.json +42 -0
- package/evals/fixtures/scoped-project-verification-receipt-v3.invalid.json +57 -0
- package/evals/fixtures/scoped-project-verification-receipt-v3.valid.json +57 -0
- package/evals/fixtures/scoped-verification-receipt-v1.invalid.json +40 -0
- package/evals/fixtures/scoped-verification-receipt-v1.valid.json +40 -0
- package/evals/fs5-artifact-archive/README.md +32 -0
- package/evals/fs5-artifact-archive/manifest.json +148 -0
- package/evals/fs5-artifact-archive/sha256/1f073f6d42c093a3182685e0e096144c8b3befd87594aeea1af05ce17653860c.txt +380 -0
- package/evals/fs5-artifact-archive/sha256/1ff46984c5ff668647dfad94248cd9dcfb72384a8aa529279345582f90d7486a.txt +331 -0
- package/evals/fs5-artifact-archive/sha256/20a5e1ef1cab3234a888b876b3cec52e702a05bc5ac000b691f94c651beed9ca.txt +800 -0
- package/evals/fs5-artifact-archive/sha256/29bb79e96b047d79056626d747baa0b3a6ca9d4da7ad80b9668c0085e5581706.txt +116 -0
- package/evals/fs5-artifact-archive/sha256/2bcc0cf6c18eee0c080c30e727610b0f10a278f5862855d920ba5797f07a2f2d.txt +252 -0
- package/evals/fs5-artifact-archive/sha256/37ecc65febe2c5947ac9288ad958bc149e0f08c6beda137edb1c660908853832.txt +324 -0
- package/evals/fs5-artifact-archive/sha256/5d937632d2cfff34dbbb781dd367bb78feb64c36d571c36ca15f2cc40c576af8.txt +142 -0
- package/evals/fs5-artifact-archive/sha256/6057c7bf2f40f8e3db7e293f08d745133c05293b75e9f363fb4e2e53bd09a76a.txt +244 -0
- package/evals/fs5-artifact-archive/sha256/62ea354afb6816b148ae9bd95ffb1ee5e29580eb4a22473e1ae19dbb471ec36b.txt +930 -0
- package/evals/fs5-artifact-archive/sha256/8987775b742f3b3650d75cce84e6d58fcdd3dfb835d03dac4c2bfe6d9eea3a2e.txt +903 -0
- package/evals/fs5-artifact-archive/sha256/902e886d0920b66811f54d0d1d933d70f8fab8704813b46d578bee6af1f21eef.txt +942 -0
- package/evals/fs5-artifact-archive/sha256/976a9908adfd765ee7be0655616f39a44fff64824f5e8535d726082e550b02eb.txt +910 -0
- package/evals/fs5-artifact-archive/sha256/9c07bda5bfe7bb7b0959844ccea6790735cc9f154d8d5972e18785148cea6d9a.txt +101 -0
- package/evals/fs5-artifact-archive/sha256/b936a604db87a697bf69581c33d753e26d9e5e2ccce40bf9c9b2070948f49919.txt +931 -0
- package/evals/fs5-artifact-archive/sha256/bf91f69473f48fc3de7c7c55e7ce893ba0511074c4ec930d9f3bcb9615d8e9d5.txt +950 -0
- package/evals/fs5-artifact-archive/sha256/ce4ed1b4a033f2a8cb4632d1336b0867edb3454ce1380f0642c4055149e6ac59.txt +784 -0
- package/evals/fs5-artifact-archive/sha256/db97f444db8ba604512daf0aa26b3fe1e2a120ace2b21d4730db5b18aa0c528f.txt +950 -0
- package/evals/fs5-causal-arm.v1.json +9 -5
- package/evals/fs5-pilot-protocol.v1.json +1 -1
- package/evals/fs5-pilot-protocol.v4.json +4 -4
- package/evals/fs5-pilot-protocol.v5.json +6 -5
- package/evals/harness-next/development-corpus.mjs +106 -0
- package/evals/harness-next/resource-budget-probe.mjs +38 -0
- package/evals/harness-next/run-calibration.mjs +83 -0
- package/evals/harness-next/run-resource-probe.mjs +55 -0
- package/evals/harness-next/selected-development-corpus.mjs +27 -0
- package/evals/harness-next.v1.json +51 -0
- package/evals/long-horizon-v1/README.md +19 -0
- package/evals/long-horizon-v1/runner.mjs +116 -48
- package/evals/long-horizon-v1/worker.mjs +77 -30
- package/evals/private-holdout-v1/CURRENT_BOUNDARY.md +53 -0
- package/evals/private-holdout-v1/README.md +5 -2
- package/evals/private-holdout-v1/public-exposure.v2.json +273 -0
- package/package.json +9 -4
- package/packages/piagent-core/README.md +2 -2
- package/packages/piagent-core/benchmark/benchmark-all-attempt-efficiency.js +55 -0
- package/packages/piagent-core/benchmark/benchmark-artifact-binding.js +49 -0
- package/packages/piagent-core/benchmark/benchmark-bootstrap.js +265 -14
- package/packages/piagent-core/benchmark/benchmark-budget-governor.js +271 -0
- package/packages/piagent-core/benchmark/benchmark-campaign.js +592 -0
- package/packages/piagent-core/benchmark/benchmark-candidate.js +8 -3
- package/packages/piagent-core/benchmark/benchmark-checkpoint.js +67 -0
- package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +269 -2
- package/packages/piagent-core/benchmark/benchmark-cli.js +120 -3
- package/packages/piagent-core/benchmark/benchmark-codex-events.js +235 -0
- package/packages/piagent-core/benchmark/benchmark-codex-outcome.js +20 -0
- package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +2 -1
- package/packages/piagent-core/benchmark/benchmark-codex-rollout.js +521 -0
- package/packages/piagent-core/benchmark/benchmark-codex.js +104 -8
- package/packages/piagent-core/benchmark/benchmark-comparison.js +284 -1
- package/packages/piagent-core/benchmark/benchmark-core.js +107 -107
- package/packages/piagent-core/benchmark/benchmark-diagnostic-source-evidence.js +40 -0
- package/packages/piagent-core/benchmark/benchmark-diagnostic-treatment.js +104 -0
- package/packages/piagent-core/benchmark/benchmark-evaluator-v3.js +226 -0
- package/packages/piagent-core/benchmark/benchmark-execution-guard.js +23 -1
- package/packages/piagent-core/benchmark/benchmark-forensics.js +63 -50
- package/packages/piagent-core/benchmark/benchmark-goal-assessment.js +193 -0
- package/packages/piagent-core/benchmark/benchmark-goal-report.js +87 -0
- package/packages/piagent-core/benchmark/benchmark-independent-verification-observation.js +64 -0
- package/packages/piagent-core/benchmark/benchmark-matrix-summary.js +141 -0
- package/packages/piagent-core/benchmark/benchmark-matrix.js +1 -0
- package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +62 -0
- package/packages/piagent-core/benchmark/benchmark-pi-home.js +1 -0
- package/packages/piagent-core/benchmark/benchmark-preflight.js +69 -8
- package/packages/piagent-core/benchmark/benchmark-process.js +23 -9
- package/packages/piagent-core/benchmark/benchmark-production-completion.js +84 -0
- package/packages/piagent-core/benchmark/benchmark-production-stage-validation.js +209 -0
- package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +162 -45
- package/packages/piagent-core/benchmark/benchmark-provider-free-owner.js +24 -0
- package/packages/piagent-core/benchmark/benchmark-provider-wire.js +378 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.d.ts +2 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.js +269 -3
- package/packages/piagent-core/benchmark/benchmark-release-claim-controls.js +132 -0
- package/packages/piagent-core/benchmark/benchmark-report.js +79 -4
- package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +280 -10
- package/packages/piagent-core/benchmark/benchmark-runner-policy.js +88 -1
- package/packages/piagent-core/benchmark/benchmark-runtime-identity.js +50 -1
- package/packages/piagent-core/benchmark/benchmark-runtime.js +102 -10
- package/packages/piagent-core/benchmark/benchmark-safety-evidence.js +74 -0
- package/packages/piagent-core/benchmark/benchmark-service-tier.js +189 -0
- package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +144 -128
- package/packages/piagent-core/benchmark/benchmark-suite-identity.js +264 -1
- package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +4 -0
- package/packages/piagent-core/benchmark/benchmark-suite.js +211 -4
- package/packages/piagent-core/benchmark/benchmark-summary-support.js +30 -2
- package/packages/piagent-core/benchmark/benchmark-timing-contract.js +189 -0
- package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +110 -139
- package/packages/piagent-core/benchmark/benchmark-transport-evidence.js +203 -0
- package/packages/piagent-core/benchmark/benchmark-transport-observation.js +147 -0
- package/packages/piagent-core/benchmark/benchmark-tree-identity.js +2 -1
- package/packages/piagent-core/benchmark/benchmark-usage.js +395 -33
- package/packages/piagent-core/benchmark/benchmark-workflow.js +136 -38
- package/packages/piagent-core/benchmark/fs5-pilot-protocol.js +21 -2
- package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
- package/packages/piagent-core/extensions/acceptance-api-baseline.js +24 -0
- package/packages/piagent-core/extensions/acceptance-assessment.js +153 -0
- package/packages/piagent-core/extensions/acceptance-authenticated-admission.d.ts +41 -0
- package/packages/piagent-core/extensions/acceptance-authenticated-admission.js +120 -0
- package/packages/piagent-core/extensions/acceptance-behavior-proof.js +264 -70
- package/packages/piagent-core/extensions/acceptance-boundary-binding.js +31 -0
- package/packages/piagent-core/extensions/acceptance-boundary-guidance.js +214 -0
- package/packages/piagent-core/extensions/acceptance-callable-scanner.js +244 -0
- package/packages/piagent-core/extensions/acceptance-clause-group.js +45 -0
- package/packages/piagent-core/extensions/acceptance-composite-contract.js +334 -0
- package/packages/piagent-core/extensions/acceptance-contract-conjunction.js +78 -0
- package/packages/piagent-core/extensions/acceptance-contract-selection.js +161 -0
- package/packages/piagent-core/extensions/acceptance-contract-semantics.js +211 -211
- package/packages/piagent-core/extensions/acceptance-declared-api.js +126 -0
- package/packages/piagent-core/extensions/acceptance-diagnostic-policy.ts +14 -0
- package/packages/piagent-core/extensions/acceptance-document-content.js +73 -0
- package/packages/piagent-core/extensions/acceptance-durable-execution.d.ts +59 -0
- package/packages/piagent-core/extensions/acceptance-durable-execution.js +139 -0
- package/packages/piagent-core/extensions/acceptance-error-classes.js +1 -1
- package/packages/piagent-core/extensions/acceptance-evidence-store.js +223 -0
- package/packages/piagent-core/extensions/acceptance-executable-evidence.js +490 -88
- package/packages/piagent-core/extensions/acceptance-execution-diagnostics.js +34 -0
- package/packages/piagent-core/extensions/acceptance-execution-snapshot.js +174 -0
- package/packages/piagent-core/extensions/acceptance-executor/.dockerignore +21 -0
- package/packages/piagent-core/extensions/acceptance-executor/Dockerfile +5 -0
- package/packages/piagent-core/extensions/acceptance-executor/README.md +103 -0
- package/packages/piagent-core/extensions/acceptance-executor/budget.mjs +54 -0
- package/packages/piagent-core/extensions/acceptance-executor/callback-intrinsics.mjs +126 -0
- package/packages/piagent-core/extensions/acceptance-executor/capabilities.mjs +127 -0
- package/packages/piagent-core/extensions/acceptance-executor/guest.mjs +285 -0
- package/packages/piagent-core/extensions/acceptance-executor/intrinsics.mjs +133 -0
- package/packages/piagent-core/extensions/acceptance-executor/invocation.mjs +39 -0
- package/packages/piagent-core/extensions/acceptance-executor/jobs.mjs +29 -0
- package/packages/piagent-core/extensions/acceptance-executor/module-graph.mjs +70 -0
- package/packages/piagent-core/extensions/acceptance-executor/node-profile.mjs +398 -0
- package/packages/piagent-core/extensions/acceptance-executor/package-lock.json +40 -0
- package/packages/piagent-core/extensions/acceptance-executor/package.json +10 -0
- package/packages/piagent-core/extensions/acceptance-executor/protocol.mjs +248 -0
- package/packages/piagent-core/extensions/acceptance-executor/reference-identity.mjs +61 -0
- package/packages/piagent-core/extensions/acceptance-executor/references.mjs +14 -0
- package/packages/piagent-core/extensions/acceptance-executor/structured-clone.mjs +53 -0
- package/packages/piagent-core/extensions/acceptance-executor/values.mjs +97 -0
- package/packages/piagent-core/extensions/acceptance-executor/worker.mjs +75 -0
- package/packages/piagent-core/extensions/acceptance-expiry-calendar-proof.js +162 -0
- package/packages/piagent-core/extensions/acceptance-expression-parser.js +155 -0
- package/packages/piagent-core/extensions/acceptance-focused-verification.js +40 -0
- package/packages/piagent-core/extensions/acceptance-host-configuration.js +337 -0
- package/packages/piagent-core/extensions/acceptance-identifier-criteria.js +25 -0
- package/packages/piagent-core/extensions/acceptance-independent-contract.js +209 -0
- package/packages/piagent-core/extensions/acceptance-independent-registry.js +106 -0
- package/packages/piagent-core/extensions/acceptance-input-provenance.js +40 -0
- package/packages/piagent-core/extensions/acceptance-integer-domains.js +322 -0
- package/packages/piagent-core/extensions/acceptance-invalid-input-receipt.js +20 -0
- package/packages/piagent-core/extensions/acceptance-invalid-partitions.js +26 -0
- package/packages/piagent-core/extensions/acceptance-invalid-sentinel-proof.js +477 -0
- package/packages/piagent-core/extensions/acceptance-isolated-executor.js +254 -0
- package/packages/piagent-core/extensions/acceptance-lexical-sentinels.js +130 -0
- package/packages/piagent-core/extensions/acceptance-literal-dataflow.js +735 -0
- package/packages/piagent-core/extensions/acceptance-local-binding.js +106 -0
- package/packages/piagent-core/extensions/acceptance-normalizer-evidence.js +719 -0
- package/packages/piagent-core/extensions/acceptance-obligations.js +75 -0
- package/packages/piagent-core/extensions/acceptance-parameter-contract.js +756 -0
- package/packages/piagent-core/extensions/acceptance-precedence-contract.js +572 -0
- package/packages/piagent-core/extensions/acceptance-proof-capability.js +26 -0
- package/packages/piagent-core/extensions/acceptance-receipt.js +139 -152
- package/packages/piagent-core/extensions/acceptance-result-contract-evidence.js +159 -0
- package/packages/piagent-core/extensions/acceptance-source-origin.js +214 -0
- package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +64 -8
- package/packages/piagent-core/extensions/acceptance-tagged-event-evidence.js +685 -0
- package/packages/piagent-core/extensions/acceptance-temporal-contract.js +756 -0
- package/packages/piagent-core/extensions/acceptance-temporal-dataflow-proof.js +618 -0
- package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +20 -2
- package/packages/piagent-core/extensions/acceptance-test-bindings.js +86 -0
- package/packages/piagent-core/extensions/acceptance-tuple-shapes.js +12 -0
- package/packages/piagent-core/extensions/context-engine.js +11 -6
- package/packages/piagent-core/extensions/criterion-context-pack.js +96 -4
- package/packages/piagent-core/extensions/failure-types.ts +2 -2
- package/packages/piagent-core/extensions/guard-types.ts +5 -1
- package/packages/piagent-core/extensions/piagent-guard.ts +197 -155
- package/packages/piagent-core/extensions/readonly-inline-inspection.ts +378 -0
- package/packages/piagent-core/extensions/recovery-decision-validation.ts +92 -0
- package/packages/piagent-core/extensions/shell-write-targets.js +15 -14
- package/packages/piagent-core/extensions/task-contract-view.js +4 -4
- package/packages/piagent-core/extensions/task-digest-migration.js +2 -2
- package/packages/piagent-core/extensions/task-journal.js +48 -3
- package/packages/piagent-core/extensions/task-runtime-audit.js +8 -2
- package/packages/piagent-core/extensions/task-state.js +74 -38
- package/packages/piagent-core/extensions/task-terminal-disposition.js +10 -0
- package/packages/piagent-core/extensions/trajectory-contract.ts +5 -0
- package/packages/piagent-core/extensions/verification-intelligence.js +60 -8
- package/packages/piagent-core/extensions/workflow-catalog.ts +98 -0
- package/packages/piagent-core/extensions/workspace-revision.js +48 -0
- package/packages/piagent-core/extensions/workspace-verification-snapshot.js +13 -0
- package/packages/piagent-core/package.json +3 -3
- package/packages/piagent-core/policies/base-policy.json +1 -0
- package/packages/piagent-core/runtime/context/adaptive-planner.ts +7 -3
- package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +60 -59
- package/packages/piagent-core/runtime/hooks/agent-start-types.ts +48 -0
- package/packages/piagent-core/runtime/hooks/completion-hook.ts +76 -83
- package/packages/piagent-core/runtime/hooks/input-hook.ts +92 -7
- package/packages/piagent-core/runtime/hooks/protected-refusal-completion.ts +86 -0
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +5 -2
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +50 -18
- package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +53 -20
- package/packages/piagent-core/runtime/hooks/tool-result-metadata.ts +9 -0
- package/packages/piagent-core/runtime/hooks/tool-result-navigation.ts +36 -0
- package/packages/piagent-core/runtime/hooks/tool-result-retrieval.ts +42 -0
- package/packages/piagent-core/runtime/input/chat-images.ts +1 -1
- package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +1 -1
- package/packages/piagent-core/runtime/inspection/same-process-bridge-proof.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +2 -2
- package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +49 -8
- package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +61 -15
- package/packages/piagent-core/runtime/inspection/workspace-file-reader.ts +2 -132
- package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +20 -0
- package/packages/piagent-core/runtime/model/service-tier-runtime.ts +242 -0
- package/packages/piagent-core/runtime/policy/source-worktree-transaction.ts +75 -14
- package/packages/piagent-core/runtime/product/activity-inspector.ts +6 -3
- package/packages/piagent-core/runtime/product/edit-verifier-timing.ts +26 -0
- package/packages/piagent-core/runtime/product/efficiency-metrics.ts +12 -7
- package/packages/piagent-core/runtime/product/operator-projections.ts +8 -3
- package/packages/piagent-core/runtime/product/task-usage-hooks.ts +78 -0
- package/packages/piagent-core/runtime/product/task-usage.ts +104 -0
- package/packages/piagent-core/runtime/quality/protected-refusal-handoff.ts +35 -0
- package/packages/piagent-core/runtime/recovery/acceptance-recovery-guidance.ts +21 -0
- package/packages/piagent-core/runtime/recovery/continuation-budget.ts +11 -2
- package/packages/piagent-core/runtime/recovery/diagnostic-delivery.ts +61 -0
- package/packages/piagent-core/runtime/recovery/handoff-projection.ts +192 -57
- package/packages/piagent-core/runtime/recovery/handoff-verifier-binding.ts +24 -0
- package/packages/piagent-core/runtime/recovery/independent-verification-recovery.ts +79 -0
- package/packages/piagent-core/runtime/recovery/recovery-policy.ts +27 -39
- package/packages/piagent-core/runtime/recovery/resume-state.ts +8 -5
- package/packages/piagent-core/runtime/registration/activity-inspector-command.ts +2 -1
- package/packages/piagent-core/runtime/registration/context-commands.ts +12 -8
- package/packages/piagent-core/runtime/registration/operator-catalogs.ts +4 -9
- package/packages/piagent-core/runtime/registration/policy-tools.ts +5 -3
- package/packages/piagent-core/runtime/registration/session-commands.ts +9 -7
- package/packages/piagent-core/runtime/registration/session-wait-tool.ts +54 -0
- package/packages/piagent-core/runtime/registration/task-completion-tools.ts +27 -11
- package/packages/piagent-core/runtime/registration/task-start-conditional-mutation.ts +45 -0
- package/packages/piagent-core/runtime/registration/task-start-guidance.ts +5 -2
- package/packages/piagent-core/runtime/registration/task-start-tool.ts +23 -23
- package/packages/piagent-core/runtime/registration/workflow-commands.ts +64 -93
- package/packages/piagent-core/runtime/session/completion-signals.ts +23 -0
- package/packages/piagent-core/runtime/session/message-signals.ts +6 -22
- package/packages/piagent-core/runtime/session/retrieval-evidence-runtime.ts +188 -0
- package/packages/piagent-core/runtime/session/runtime-state.ts +29 -35
- package/packages/piagent-core/runtime/session/system-prompt.ts +3 -3
- package/packages/piagent-core/runtime/session/uncertain-send-continuation.ts +231 -0
- package/packages/piagent-core/runtime/session/usage.ts +4 -3
- package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +6 -6
- package/packages/piagent-core/runtime/tools/phase-tool-runtime.ts +1 -1
- package/packages/piagent-core/runtime/tools/phase-tools.ts +3 -2
- package/packages/piagent-core/runtime/tools/session-wait.ts +42 -0
- package/packages/piagent-core/runtime/tools/tool-groups.ts +10 -3
- package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +192 -5
- package/packages/piagent-core/runtime/trajectory/trajectory-types.ts +3 -2
- package/packages/piagent-core/runtime/verification/acceptance-api-baseline.js +488 -0
- package/packages/piagent-core/runtime/verification/completion-preparation.ts +22 -0
- package/packages/piagent-core/runtime/verification/composite-completion-finalizer.ts +105 -0
- package/packages/piagent-core/runtime/verification/composite-journal-anchor.ts +181 -0
- package/packages/piagent-core/runtime/verification/composite-runtime-binding.ts +76 -0
- package/packages/piagent-core/runtime/verification/composite-scoped-mediation.ts +318 -0
- package/packages/piagent-core/runtime/verification/composite-session-persistence.ts +175 -0
- package/packages/piagent-core/runtime/verification/composite-task-publication.ts +273 -0
- package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +11 -11
- package/packages/piagent-core/runtime/verification/host-project-verification.ts +71 -0
- package/packages/piagent-core/runtime/verification/independent-acceptance-runtime.ts +500 -0
- package/packages/piagent-core/runtime/verification/runtime-assurance-facts.ts +500 -0
- package/packages/piagent-core/runtime/verification/runtime-contract-runner.ts +107 -0
- package/packages/piagent-core/runtime/verification/shell-verification-snapshots.ts +56 -0
- package/packages/piagent-core/runtime/workflows/change-clarification.ts +61 -0
- package/packages/piagent-core/runtime/workflows/input-routing.ts +21 -14
- package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +44 -7
- package/packages/piagent-core/runtime/workflows/task-followup-policy.ts +163 -0
- package/packages/piagent-core/runtime/workflows/task-intake.ts +221 -242
- package/packages/piagent-core/runtime/workflows/task-repair-intent.ts +67 -0
- package/packages/piagent-core/runtime/workflows/task-scope-resolution.ts +83 -0
- package/packages/piagent-core/runtime/workflows/webui-runtime-command.ts +5 -2
- package/packages/piagent-core/runtime/workflows/webui-workflow.ts +39 -32
- package/packages/piagent-core/runtime/workflows/workflow-follow-up.ts +33 -0
- package/packages/piagent-core/security/workspace-file-reader.ts +132 -0
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-B4XehTCU.js → MarkdownMessage-DGk34zJT.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{index-BV-_03yl.css → index-DVahUVWy.css} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DiKRmCEP.js +176 -0
- package/packages/piagent-webui/dist/client/index.html +2 -2
- package/packages/piagent-webui/extension/dispatch-user-entry.ts +13 -0
- package/packages/piagent-webui/extension/piagent-webui.ts +10 -2
- package/packages/piagent-webui/extension/review-controller.ts +29 -6
- package/packages/piagent-webui/extension/same-session-bridge.ts +6 -7
- package/packages/piagent-webui/extension/session-stream-adapter.ts +60 -11
- package/packages/piagent-webui/extension/source-mutation-controller.ts +29 -3
- package/packages/piagent-webui/extension/source-open-controller.ts +29 -7
- package/packages/piagent-webui/extension/source-revert-controller.ts +26 -3
- package/packages/piagent-webui/gateway/gateway-events.ts +22 -5
- package/packages/piagent-webui/gateway/gateway-service.ts +7 -2
- package/packages/piagent-webui/gateway/gateway-session-stream.ts +141 -19
- package/packages/piagent-webui/gateway/rpc-ui-context.ts +34 -9
- package/packages/piagent-webui/gateway/runtime-command-controller.ts +46 -6
- package/packages/piagent-webui/gateway/runtime-session-controls.ts +17 -2
- package/packages/piagent-webui/gateway/session-catalog.ts +9 -3
- package/packages/piagent-webui/gateway/session-command-controller.ts +29 -9
- package/packages/piagent-webui/gateway/session-effective-options.ts +2 -9
- package/packages/piagent-webui/gateway/session-inspection-registry.ts +11 -2
- package/packages/piagent-webui/gateway/session-operation-settlement.ts +28 -0
- package/packages/piagent-webui/gateway/session-prompt-dispatch.ts +37 -0
- package/packages/piagent-webui/gateway/session-runtime-close.ts +36 -0
- package/packages/piagent-webui/gateway/session-runtime-factory.ts +183 -6
- package/packages/piagent-webui/gateway/session-runtime-ownership.ts +48 -0
- package/packages/piagent-webui/gateway/session-runtime-state.ts +24 -0
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +114 -114
- package/packages/piagent-webui/server/core-inspection-provider.ts +73 -14
- package/packages/piagent-webui/server/loopback-server.ts +9 -7
- package/packages/piagent-webui/server/terminal-delivery-receipt.ts +144 -0
- package/packages/piagent-webui/server/transcript-projection.ts +65 -12
- package/packages/piagent-webui/shared/message-correlation.ts +25 -0
- package/schemas/approved-host-contracts.schema.json +973 -0
- package/schemas/benchmark-attempt-outcome.schema.json +303 -0
- package/schemas/benchmark-independent-verification-plan.schema.json +34 -0
- package/schemas/composite-criterion.schema.json +788 -0
- package/schemas/contract-family-library.schema.json +28 -0
- package/schemas/contract-selection-recipe.schema.json +31 -0
- package/schemas/failure-evidence.schema.json +2 -2
- package/schemas/helper-request.schema.json +16 -4
- package/schemas/host-contract-plan.schema.json +25 -0
- package/schemas/piagent-webui/gateway-protocol-v1.schema.json +16 -2
- package/schemas/piagent-webui/runtime-command-v1.schema.json +26 -3
- package/schemas/piagent-webui/runtime-event-v2.schema.json +32 -1
- package/schemas/piagent-webui/session-live-state-v1.schema.json +2 -0
- package/schemas/piagent-webui/snapshot-v1.schema.json +3 -0
- package/schemas/piagent-webui/source-change-v1.schema.json +12 -0
- package/schemas/piagent-webui/transcript-v1.schema.json +2 -1
- package/schemas/public-contracts/codex-mcp-metadata-v1.schema.json +206 -0
- package/schemas/public-contracts/codex-mcp-metadata-v2.schema.json +228 -0
- package/schemas/public-contracts/codex-mcp-metadata-v3.schema.json +233 -0
- package/schemas/public-contracts/revocation-v1.schema.json +87 -0
- package/schemas/public-contracts/subscription-contract-v1.schema.json +76 -0
- package/schemas/scoped-project-verification-receipt-v2.schema.json +83 -0
- package/schemas/scoped-project-verification-receipt-v3.schema.json +295 -0
- package/schemas/scoped-verification-receipt-v1.schema.json +76 -0
- package/schemas/task-contract.schema.json +30 -0
- package/scripts/approve-independent-verification.mjs +57 -0
- package/scripts/benchmark-arm-observer.mjs +320 -0
- package/scripts/benchmark-budget-ipc.mjs +34 -0
- package/scripts/benchmark-budget-launcher.mjs +91 -0
- package/scripts/benchmark-budget-processes.mjs +133 -0
- package/scripts/benchmark-budget-publication.mjs +228 -0
- package/scripts/benchmark-budget-runtime.mjs +136 -0
- package/scripts/benchmark-candidate-ablation.mjs +265 -0
- package/scripts/benchmark-codex-journey.mjs +406 -0
- package/scripts/benchmark-independent-verification.mjs +628 -0
- package/scripts/benchmark-journey-outcome.mjs +92 -0
- package/scripts/benchmark-production-v3-human-review.mjs +192 -0
- package/scripts/benchmark-public-input-catalog.mjs +158 -0
- package/scripts/benchmark-registered-plan-author.mjs +355 -0
- package/scripts/benchmark-registered-plan-recipe-support.mjs +85 -0
- package/scripts/benchmark-registered-plan-recipes-backend.mjs +165 -0
- package/scripts/benchmark-registered-plan-recipes-data.mjs +164 -0
- package/scripts/benchmark-registered-plan-recipes-platform.mjs +165 -0
- package/scripts/benchmark-runner-completion.mjs +133 -0
- package/scripts/benchmark-runner-configuration.mjs +159 -0
- package/scripts/benchmark-runner-core.mjs +217 -388
- package/scripts/benchmark-runner-finalization.mjs +140 -27
- package/scripts/benchmark-runner-provider-boundary.mjs +44 -0
- package/scripts/benchmark-runner-schedule.mjs +256 -0
- package/scripts/benchmark-runner-support.mjs +136 -4
- package/scripts/benchmark-runner.mjs +95 -18
- package/scripts/benchmark-scoped-broker-custody.mjs +483 -0
- package/scripts/benchmark-scoped-docs-verifier.mjs +203 -0
- package/scripts/benchmark-scoped-frozen-qualification.mjs +676 -0
- package/scripts/benchmark-scoped-pi-router.mjs +196 -0
- package/scripts/benchmark-scoped-project-verification-receipt.mjs +49 -0
- package/scripts/benchmark-scoped-project-verifier.mjs +461 -0
- package/scripts/benchmark-scoped-session-custody.mjs +599 -0
- package/scripts/benchmark-scoped-session-factory.mjs +342 -0
- package/scripts/benchmark-scoped-tool-broker.mjs +523 -0
- package/scripts/benchmark-scoped-verification-supervisor.mjs +773 -0
- package/scripts/benchmark-session-evaluator.mjs +169 -0
- package/scripts/benchmark-session-provider-boundary.mjs +62 -0
- package/scripts/benchmark-session-usage.mjs +28 -0
- package/scripts/benchmark-session.mjs +343 -50
- package/scripts/benchmark-webui-journey.mjs +678 -0
- package/scripts/check-public-wording.mjs +46 -0
- package/scripts/fs4-readiness-evaluation.mjs +7 -1
- package/scripts/phase-tools-evaluation.mjs +1 -0
- package/scripts/pi-auto.sh +7 -1
- package/scripts/pi-usage-history.mjs +201 -11
- package/scripts/piagent-cli.mjs +8 -0
- package/scripts/private-holdout-readiness.mjs +7 -1
- package/scripts/public-evaluation-exposure.mjs +140 -0
- package/scripts/select-independent-verification.mjs +62 -0
- package/scripts/typescript-loader.mjs +135 -1
- package/scripts/update-global.mjs +6 -7
- package/scripts/verify-local.sh +36 -55
- package/scripts/verify-release-identity.mjs +5 -3
- package/packages/piagent-webui/dist/client/assets/index-CgOEyRPG.js +0 -176
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { benchmarkCommandIdentity } from "../packages/piagent-core/benchmark/benchmark-runtime-identity.js";
|
|
5
|
+
import { installedContractVerifierDigest, openHostContractConfiguration, validateHostContractPlan, writeHostContractApproval } from "../packages/piagent-core/extensions/acceptance-host-configuration.js";
|
|
6
|
+
import { buildAcceptanceReceipt } from "../packages/piagent-core/extensions/acceptance-receipt.js";
|
|
7
|
+
import { effectiveProtectedPaths } from "../packages/piagent-core/extensions/context-index-policy.js";
|
|
8
|
+
import { DURABLE_EXECUTION_VERSION } from "../packages/piagent-core/extensions/acceptance-durable-execution.js";
|
|
9
|
+
import { compileIndependentContract, compareIndependentExecution } from "../packages/piagent-core/extensions/acceptance-independent-contract.js";
|
|
10
|
+
import { EXECUTION_SNAPSHOT_VERSION } from "../packages/piagent-core/extensions/acceptance-execution-snapshot.js";
|
|
11
|
+
import { parseRequest, parseResponse } from "../packages/piagent-core/extensions/acceptance-executor/protocol.mjs";
|
|
12
|
+
import { operatorRequestDigest } from "../packages/piagent-core/extensions/task-state.js";
|
|
13
|
+
import { redactSensitiveText } from "../packages/piagent-core/extensions/redaction-core.js";
|
|
14
|
+
import { extractLocalImagePathCandidates } from "../packages/piagent-core/runtime/input/chat-images.ts";
|
|
15
|
+
import { boundedOperatorRequest } from "../packages/piagent-core/runtime/registration/operator-request-intake.ts";
|
|
16
|
+
import { automaticTaskExpectedOutput } from "../packages/piagent-core/runtime/registration/task-start-conditional-mutation.ts";
|
|
17
|
+
import { LONG_INPUT_CHARS } from "../packages/piagent-core/runtime/runtime-limits.ts";
|
|
18
|
+
import { agentStartTaskRequest, looksLikeGovernedBoilerplate } from "../packages/piagent-core/runtime/workflows/input-routing.ts";
|
|
19
|
+
import { automaticAcceptanceCriteria, automaticTaskIntakeMode, automaticTaskMutationPolicy,
|
|
20
|
+
automaticTaskSummary } from "../packages/piagent-core/runtime/workflows/task-intake.ts";
|
|
21
|
+
import { buildWebUiWorkflowCommand, isWebUiWorkflowId } from "../packages/piagent-core/runtime/workflows/webui-workflow.ts";
|
|
22
|
+
import { buildWorkflowFollowUp } from "../packages/piagent-core/runtime/workflows/workflow-follow-up.ts";
|
|
23
|
+
import { compositeTaskPublicationDigest, openCompositeTaskPublicationStore } from "../packages/piagent-core/runtime/verification/composite-task-publication.ts";
|
|
24
|
+
|
|
25
|
+
export const BENCHMARK_VERIFICATION_PLAN_VERSION = "benchmark-independent-verification-plan-v1";
|
|
26
|
+
export const NODE_BENCHMARK_VERIFICATION_PLAN_VERSION = "benchmark-independent-verification-plan-v2";
|
|
27
|
+
const HASH = /^[a-f0-9]{64}$/;
|
|
28
|
+
const hash = (value) => createHash("sha256").update(value).digest("hex");
|
|
29
|
+
const exact = (value, fields) => value && typeof value === "object" && !Array.isArray(value)
|
|
30
|
+
&& Object.keys(value).length === fields.length && fields.every(field => Object.hasOwn(value, field));
|
|
31
|
+
const freeze = (value) => { if (value && typeof value === "object") { Object.values(value).forEach(freeze); Object.freeze(value); } return value; };
|
|
32
|
+
const inside = (root, file) => { const relative = path.relative(fs.realpathSync.native(root), file);
|
|
33
|
+
return !relative || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative)); };
|
|
34
|
+
|
|
35
|
+
function registeredPlanForSurface(plan, surface) {
|
|
36
|
+
if (!["piagent", "codex-cli"].includes(surface)) throw new TypeError("Invalid registered verification surface");
|
|
37
|
+
const selected = structuredClone(plan);
|
|
38
|
+
for (const contract of selected.contracts) {
|
|
39
|
+
if (contract.route !== "composite") continue;
|
|
40
|
+
const identity = contract.planContext.identity;
|
|
41
|
+
if (!exact(identity, ["suiteDigest", "configDigest", "armDigests"])
|
|
42
|
+
|| !exact(identity.armDigests, ["piagent", "codex-cli"])
|
|
43
|
+
|| ![identity.suiteDigest, identity.configDigest, identity.armDigests.piagent,
|
|
44
|
+
identity.armDigests["codex-cli"]].every(value => HASH.test(value))) {
|
|
45
|
+
throw new TypeError("Invalid registered surface-indexed composite identity");
|
|
46
|
+
}
|
|
47
|
+
contract.planContext.identity = { suiteDigest: identity.suiteDigest,
|
|
48
|
+
configDigest: identity.configDigest, armDigest: identity.armDigests[surface] };
|
|
49
|
+
}
|
|
50
|
+
validateHostContractPlan(selected);
|
|
51
|
+
return freeze(selected);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function resolvedJourneyTurns(scenario, suiteRoot, resolveSuiteEntry) {
|
|
55
|
+
if (!scenario.userJourney) return null;
|
|
56
|
+
return scenario.userJourney.turns.map((turn) => {
|
|
57
|
+
if (Object.hasOwn(turn, "workflow") && !isWebUiWorkflowId(turn.workflow)) throw new TypeError("Unsupported verification workflow");
|
|
58
|
+
return {
|
|
59
|
+
id: turn.id,
|
|
60
|
+
message: fs.readFileSync(resolveSuiteEntry(suiteRoot, turn.prompt, `journey prompt ${scenario.id}/${turn.id}`), "utf8").trim(),
|
|
61
|
+
reconnectBefore: turn.reconnectBefore === true,
|
|
62
|
+
receiptUncertain: turn.receiptUncertain === true,
|
|
63
|
+
...(turn.workflow ? { workflow: turn.workflow } : {})
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Prospective Piagent request bytes only; no task admission, criterion or approval authority. */
|
|
69
|
+
export function benchmarkVerificationOperatorRequest({ message, workflow }) {
|
|
70
|
+
if (workflow != null && !isWebUiWorkflowId(workflow)) throw new TypeError("Unsupported verification workflow");
|
|
71
|
+
const request = buildWebUiWorkflowCommand(null, message);
|
|
72
|
+
// Raw input may be rewritten by commands, boilerplate collapse or a context-
|
|
73
|
+
// dependent fresh-session handoff. Explicit workflow follow-ups originate
|
|
74
|
+
// from the extension, so those preflight rewrites do not apply to them.
|
|
75
|
+
if (!workflow && (request.startsWith("/") || looksLikeGovernedBoilerplate(request) || request.length >= LONG_INPUT_CHARS)) {
|
|
76
|
+
throw new TypeError("Unsupported verification request ingress: declare a workflow or use bounded plain prose");
|
|
77
|
+
}
|
|
78
|
+
const delivered = workflow ? buildWorkflowFollowUp(workflow, request) : request;
|
|
79
|
+
// Attachment rewriting depends on project files and policy. Detect possible
|
|
80
|
+
// paths without reading them; never guess which image will be attached.
|
|
81
|
+
if (extractLocalImagePathCandidates(delivered, "/").length) throw new TypeError("Unsupported verification image request ingress");
|
|
82
|
+
const safeRequest = boundedOperatorRequest(agentStartTaskRequest(delivered), value => redactSensitiveText(value).text);
|
|
83
|
+
if (!safeRequest) throw new TypeError("Unbound verification operator request");
|
|
84
|
+
return safeRequest;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Prospective Piagent request identity only; no task admission, criterion or approval authority. */
|
|
88
|
+
export function benchmarkVerificationRequestDigest(input) {
|
|
89
|
+
return operatorRequestDigest(benchmarkVerificationOperatorRequest(input));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Preview the actual frozen runtime, not a live checkout with different build assets. */
|
|
93
|
+
export function benchmarkVerificationBinding({ installedRoot, suiteDigest }) {
|
|
94
|
+
if (!HASH.test(suiteDigest)) throw new TypeError("Invalid frozen verification suite digest");
|
|
95
|
+
return Object.freeze({ kind: "benchmark-verification-binding-v1", suiteDigest,
|
|
96
|
+
verifierDigest: installedContractVerifierDigest(installedRoot), approval: "not-granted" });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function prepareBenchmarkVerification({ options, resumeState, registeredMeasurement, ...scope }) {
|
|
100
|
+
if (registeredMeasurement) {
|
|
101
|
+
if (options.verificationPlan || options.approveVerification) {
|
|
102
|
+
throw new Error("Registered measurement supplies its signed verification plans; legacy verification options are forbidden");
|
|
103
|
+
}
|
|
104
|
+
const plan = loadRegisteredBenchmarkVerificationPlan({ registeredMeasurement, ...scope });
|
|
105
|
+
if (resumeState && JSON.stringify(plan.identity) !== JSON.stringify(resumeState.manifest.verificationPlan?.identity ?? null)) {
|
|
106
|
+
throw new Error("Cannot resume benchmark: registered independent verification configuration changed");
|
|
107
|
+
}
|
|
108
|
+
// The detached trusted registration is the approval boundary. This flag is
|
|
109
|
+
// internal runner state; the registered CLI still rejects an arbitrary
|
|
110
|
+
// --approve-verification or --verification-plan input.
|
|
111
|
+
options.approveVerification = true;
|
|
112
|
+
return plan;
|
|
113
|
+
}
|
|
114
|
+
if (resumeState) {
|
|
115
|
+
if (options.verificationPlan && options.verificationPlan !== resumeState.manifest.verificationPlan?.file) throw new Error("Cannot change the verification plan on resume");
|
|
116
|
+
options.verificationPlan = resumeState.manifest.verificationPlan?.file;
|
|
117
|
+
}
|
|
118
|
+
if (options.approveVerification && !options.verificationPlan) throw new Error("--approve-verification requires a verification plan");
|
|
119
|
+
const plan = options.verificationPlan ? loadBenchmarkVerificationPlan({ ...scope, file: options.verificationPlan }) : null;
|
|
120
|
+
if (resumeState && JSON.stringify(plan?.identity ?? null) !== JSON.stringify(resumeState.manifest.verificationPlan?.identity ?? null)) {
|
|
121
|
+
throw new Error("Cannot resume benchmark: independent verification configuration changed");
|
|
122
|
+
}
|
|
123
|
+
if (plan && !options.dryRun && !options.preflightOnly && !options.approveVerification) {
|
|
124
|
+
throw new Error("Independent verification requires explicit --approve-verification; --yes is not approval");
|
|
125
|
+
}
|
|
126
|
+
if (plan) options.keepWorkspaces = true;
|
|
127
|
+
return plan;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function readRegisteredAsset(registeredMeasurement, relativePath) {
|
|
131
|
+
const root = registeredMeasurement?.assetRoot;
|
|
132
|
+
if (typeof root !== "string" || !path.isAbsolute(root) || fs.realpathSync.native(root) !== root) {
|
|
133
|
+
throw new Error("Registered verification asset root is invalid");
|
|
134
|
+
}
|
|
135
|
+
const entry = registeredMeasurement?.inventory?.entries?.find(item => item.path === relativePath);
|
|
136
|
+
if (!entry || !HASH.test(entry.sha256) || !Number.isSafeInteger(entry.bytes) || entry.bytes < 1 || entry.bytes > 2 * 1024 * 1024) {
|
|
137
|
+
throw new Error("Registered verification plan is absent from the approved inventory");
|
|
138
|
+
}
|
|
139
|
+
const file = path.join(root, ...relativePath.split("/")), relative = path.relative(root, file);
|
|
140
|
+
if (relative.split(path.sep).join("/") !== relativePath || relative.startsWith("../") || path.isAbsolute(relative)) {
|
|
141
|
+
throw new Error("Registered verification plan escapes its approved root");
|
|
142
|
+
}
|
|
143
|
+
const before = fs.lstatSync(file, { bigint: true });
|
|
144
|
+
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n || before.size !== BigInt(entry.bytes)) {
|
|
145
|
+
throw new Error("Registered verification plan is not one approved regular file");
|
|
146
|
+
}
|
|
147
|
+
const fd = fs.openSync(file, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
|
|
148
|
+
try {
|
|
149
|
+
const descriptor = fs.fstatSync(fd, { bigint: true }), bytes = fs.readFileSync(fd), after = fs.fstatSync(fd,
|
|
150
|
+
{ bigint: true }), current = fs.lstatSync(file, { bigint: true }), fields =
|
|
151
|
+
["dev", "ino", "mode", "nlink", "size", "mtimeNs", "ctimeNs"];
|
|
152
|
+
if (bytes.length !== entry.bytes || fields.some(name => before[name] !== descriptor[name]
|
|
153
|
+
|| before[name] !== after[name] || before[name] !== current[name]) || hash(bytes) !== entry.sha256) {
|
|
154
|
+
throw new Error("Registered verification plan changed during approved read");
|
|
155
|
+
}
|
|
156
|
+
return bytes;
|
|
157
|
+
} finally { fs.closeSync(fd); }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function registeredText(bytes, label) {
|
|
161
|
+
let text;
|
|
162
|
+
try { text = new TextDecoder("utf-8", { fatal: true }).decode(bytes).trim(); }
|
|
163
|
+
catch { throw new Error(`Registered ${label} is not UTF-8`); }
|
|
164
|
+
if (!text || !text.isWellFormed()) throw new Error(`Registered ${label} is empty or malformed`);
|
|
165
|
+
return Object.freeze({ text, bytes: Buffer.byteLength(text), sha256: hash(text) });
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function suitePromptText(suiteRoot, resolveSuiteEntry, relativePath, label) {
|
|
169
|
+
const file = resolveSuiteEntry(suiteRoot, relativePath, label);
|
|
170
|
+
return registeredText(fs.readFileSync(file), label);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function installedJson(installedRoot, relativePath, label) {
|
|
174
|
+
const file = path.join(installedRoot, ...relativePath.split("/"));
|
|
175
|
+
if (!inside(installedRoot, file) || fs.realpathSync.native(file) !== file) {
|
|
176
|
+
throw new Error(`Installed ${label} escapes the frozen candidate`);
|
|
177
|
+
}
|
|
178
|
+
const stat = fs.lstatSync(file);
|
|
179
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size < 2 || stat.size > 2 * 1024 * 1024) {
|
|
180
|
+
throw new Error(`Installed ${label} is not a bounded regular file`);
|
|
181
|
+
}
|
|
182
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Provider-free preview of the exact runtime receipt used by registered-plan
|
|
186
|
+
* loading. This creates no approval, execution, assessment or PASS authority. */
|
|
187
|
+
export function benchmarkVerificationReceiptForTurn(turn, { profile, policy }) {
|
|
188
|
+
const query = benchmarkVerificationOperatorRequest(turn);
|
|
189
|
+
const protectedPaths = effectiveProtectedPaths(policy, profile).readProtectedPaths;
|
|
190
|
+
const changeMode = automaticTaskIntakeMode(query, protectedPaths);
|
|
191
|
+
if (!changeMode) throw new Error("Registered primary request is not admitted by the frozen runtime intake");
|
|
192
|
+
const mutationPolicy = automaticTaskMutationPolicy(query, changeMode);
|
|
193
|
+
const redact = value => redactSensitiveText(String(value ?? "")).text;
|
|
194
|
+
const summary = redact(automaticTaskSummary(query));
|
|
195
|
+
const expectedOutput = redact(automaticTaskExpectedOutput(mutationPolicy));
|
|
196
|
+
const acceptanceCriteria = automaticAcceptanceCriteria(query,
|
|
197
|
+
mutationPolicy === "forbidden" ? "read-only" : changeMode, mutationPolicy).map(redact);
|
|
198
|
+
const built = buildAcceptanceReceipt({
|
|
199
|
+
summary, expectedOutput, acceptanceCriteria, changeMode, mutationPolicy,
|
|
200
|
+
outOfScope: ["Unrelated files and behavior outside the operator request."],
|
|
201
|
+
protectedPaths: profile.protectedPaths ?? [], source: "runtime",
|
|
202
|
+
generatedAt: "1970-01-01T00:00:00.000Z"
|
|
203
|
+
});
|
|
204
|
+
return Object.freeze({ query, changeMode, mutationPolicy,
|
|
205
|
+
criteria: built.receipt.criteria.map((criterion, index) => Object.freeze({
|
|
206
|
+
criterionId: criterion.id, criterionHash: criterion.hash, criterionText: built.acceptanceCriteria[index]
|
|
207
|
+
})) });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function registeredCatalogAndInputs({ registeredMeasurement, scenarios, suiteRoot, resolveSuiteEntry }) {
|
|
211
|
+
const catalogBytes = readRegisteredAsset(registeredMeasurement, "catalog.json");
|
|
212
|
+
let catalog;
|
|
213
|
+
try { catalog = JSON.parse(catalogBytes); }
|
|
214
|
+
catch { throw new Error("Registered public input catalog is not JSON"); }
|
|
215
|
+
const fields = ["schemaVersion", "kind", "authority", "suiteId", "scenarioCount", "publicInputCount",
|
|
216
|
+
"variantRoleCounts", "scenarios"];
|
|
217
|
+
const scenarioIds = scenarios.map(item => item.id), payload = registeredMeasurement.payload;
|
|
218
|
+
if (!exact(catalog, fields) || catalog.schemaVersion !== 1
|
|
219
|
+
|| catalog.kind !== "benchmark-public-input-catalog-v1" || catalog.authority !== "none"
|
|
220
|
+
|| catalog.suiteId !== payload.suiteId || catalog.scenarioCount !== 27 || catalog.publicInputCount !== 54
|
|
221
|
+
|| hash(JSON.stringify(catalog)) !== payload.catalogDigest
|
|
222
|
+
|| JSON.stringify(payload.scenarioIds) !== JSON.stringify(scenarioIds)
|
|
223
|
+
|| !Array.isArray(catalog.scenarios) || catalog.scenarios.length !== scenarios.length
|
|
224
|
+
|| JSON.stringify(catalog.scenarios.map(item => item.scenarioId)) !== JSON.stringify(scenarioIds)) {
|
|
225
|
+
throw new Error("Registered public input catalog does not match the detached measurement");
|
|
226
|
+
}
|
|
227
|
+
const changed = new Set(payload.promptRolesChanged), inputs = new Map();
|
|
228
|
+
let publicInputCount = 0;
|
|
229
|
+
for (const [scenarioIndex, scenario] of scenarios.entries()) {
|
|
230
|
+
const entry = catalog.scenarios[scenarioIndex], sourceTurns = scenario.userJourney?.turns;
|
|
231
|
+
if (!exact(entry, ["scenarioId", "variantRole", "planRef", "turnCount", "turns"])
|
|
232
|
+
|| !Array.isArray(sourceTurns) || entry.scenarioId !== scenario.id
|
|
233
|
+
|| entry.variantRole !== scenario.variantRole || entry.planRef !== `plan:${scenario.id}`
|
|
234
|
+
|| entry.turnCount !== sourceTurns.length || !Array.isArray(entry.turns)
|
|
235
|
+
|| entry.turns.length !== sourceTurns.length) {
|
|
236
|
+
throw new Error("Registered public input scenario does not match the frozen base suite");
|
|
237
|
+
}
|
|
238
|
+
let amendmentUses = 0;
|
|
239
|
+
const turns = sourceTurns.map((source, index) => {
|
|
240
|
+
const amended = changed.has(scenario.id) && source.prompt === scenario.prompt;
|
|
241
|
+
if (amended) amendmentUses += 1;
|
|
242
|
+
const prompt = amended
|
|
243
|
+
? registeredText(readRegisteredAsset(registeredMeasurement,
|
|
244
|
+
`measurement/prompts/${scenario.id}.md`), `prompt amendment ${scenario.id}`)
|
|
245
|
+
: suitePromptText(suiteRoot, resolveSuiteEntry, source.prompt,
|
|
246
|
+
`registered public input ${scenario.id}/${source.id}`);
|
|
247
|
+
const turn = Object.freeze({ id: source.id, message: prompt.text,
|
|
248
|
+
reconnectBefore: source.reconnectBefore === true, receiptUncertain: source.receiptUncertain === true,
|
|
249
|
+
...(source.workflow ? { workflow: source.workflow } : {}) });
|
|
250
|
+
const projectedDigest = benchmarkVerificationRequestDigest(turn), registered = entry.turns[index];
|
|
251
|
+
const binding = { version: 1, suiteId: catalog.suiteId, scenarioId: scenario.id,
|
|
252
|
+
planRef: entry.planRef, variantRole: entry.variantRole, turnIndex: index + 1,
|
|
253
|
+
turnId: source.id, promptPath: source.prompt, promptSha256: prompt.sha256,
|
|
254
|
+
promptBytes: prompt.bytes, workflow: source.workflow ?? null,
|
|
255
|
+
reconnectBefore: source.reconnectBefore === true, receiptUncertain: source.receiptUncertain === true,
|
|
256
|
+
operatorRequestDigest: projectedDigest };
|
|
257
|
+
if (!exact(registered, ["index", "turnId", "promptPath", "promptSha256", "promptBytes", "workflow",
|
|
258
|
+
"reconnectBefore", "receiptUncertain", "operatorRequestDigest", "bindingDigest"])
|
|
259
|
+
|| registered.index !== index + 1 || registered.turnId !== source.id
|
|
260
|
+
|| registered.promptPath !== source.prompt || registered.promptSha256 !== prompt.sha256
|
|
261
|
+
|| registered.promptBytes !== prompt.bytes || registered.workflow !== (source.workflow ?? null)
|
|
262
|
+
|| registered.reconnectBefore !== (source.reconnectBefore === true)
|
|
263
|
+
|| registered.receiptUncertain !== (source.receiptUncertain === true)
|
|
264
|
+
|| registered.operatorRequestDigest !== projectedDigest
|
|
265
|
+
|| registered.bindingDigest !== hash(JSON.stringify(binding))) {
|
|
266
|
+
throw new Error("Registered public turn does not match the dispatched input");
|
|
267
|
+
}
|
|
268
|
+
publicInputCount += 1;
|
|
269
|
+
return turn;
|
|
270
|
+
});
|
|
271
|
+
if (changed.has(scenario.id) !== (amendmentUses === 1)) {
|
|
272
|
+
throw new Error("Registered prompt amendment does not bind exactly one primary turn");
|
|
273
|
+
}
|
|
274
|
+
const primary = changed.has(scenario.id)
|
|
275
|
+
? registeredText(readRegisteredAsset(registeredMeasurement,
|
|
276
|
+
`measurement/prompts/${scenario.id}.md`), `primary prompt ${scenario.id}`).text
|
|
277
|
+
: suitePromptText(suiteRoot, resolveSuiteEntry, scenario.prompt,
|
|
278
|
+
`registered primary prompt ${scenario.id}`).text;
|
|
279
|
+
const selected = entry.variantRole === "interaction"
|
|
280
|
+
? turns.find(turn => turn.id === "implement") : turns[0];
|
|
281
|
+
if (!selected) throw new Error("Registered scenario has no primary verification turn");
|
|
282
|
+
inputs.set(scenario.id, freeze({ scenarioId: scenario.id, role: entry.variantRole,
|
|
283
|
+
prompt: primary, turns, selected }));
|
|
284
|
+
}
|
|
285
|
+
if (publicInputCount !== catalog.publicInputCount || changed.size !== payload.promptRolesChanged.length) {
|
|
286
|
+
throw new Error("Registered public input catalog count changed");
|
|
287
|
+
}
|
|
288
|
+
return Object.freeze({ catalog: freeze(catalog), catalogBytes, inputs });
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Load the exact detached-registration plan assets. The registration is the
|
|
293
|
+
* human approval boundary; this loader still proves plan/input/runtime equality
|
|
294
|
+
* before creating any per-run host authority.
|
|
295
|
+
*/
|
|
296
|
+
export function loadRegisteredBenchmarkVerificationPlan({
|
|
297
|
+
registeredMeasurement, installedRoot, suiteDigest, scenarios, suiteRoot, resolveSuiteEntry
|
|
298
|
+
}) {
|
|
299
|
+
const root = registeredMeasurement?.assetRoot;
|
|
300
|
+
if (typeof root !== "string" || !path.isAbsolute(root) || fs.realpathSync.native(root) !== root) {
|
|
301
|
+
throw new Error("Registered verification asset root is invalid");
|
|
302
|
+
}
|
|
303
|
+
if (inside(installedRoot, root) || inside(suiteRoot, root)) {
|
|
304
|
+
throw new Error("Registered verification assets must be outside candidate and base suite source");
|
|
305
|
+
}
|
|
306
|
+
if (registeredMeasurement.payload.baseSuiteDigest !== suiteDigest) {
|
|
307
|
+
throw new Error("Registered verification does not match the frozen base suite");
|
|
308
|
+
}
|
|
309
|
+
const verifierDigest = installedContractVerifierDigest(installedRoot);
|
|
310
|
+
const { catalogBytes, inputs } = registeredCatalogAndInputs({
|
|
311
|
+
registeredMeasurement, scenarios, suiteRoot, resolveSuiteEntry
|
|
312
|
+
});
|
|
313
|
+
const nodeBytes = readRegisteredAsset(registeredMeasurement, "measurement/node-workload-api-v1.json");
|
|
314
|
+
const nodeProfile = JSON.parse(nodeBytes);
|
|
315
|
+
if (nodeProfile?.schemaVersion !== 1 || nodeProfile?.kind !== "node-workload-api-profile-v1"
|
|
316
|
+
|| nodeProfile?.profile?.digest !== registeredMeasurement.payload.nodeProfileDigest
|
|
317
|
+
|| !/^sha256:[a-f0-9]{64}$/.test(String(nodeProfile?.workerImage?.id ?? ""))
|
|
318
|
+
|| JSON.stringify(nodeProfile?.publicCoverage?.allScenarioIds) !== JSON.stringify(scenarios.map(item => item.id))) {
|
|
319
|
+
throw new Error("Registered Node verifier profile does not match the measurement");
|
|
320
|
+
}
|
|
321
|
+
const noncode = new Set(nodeProfile.publicCoverage.noncodeScenarioIds);
|
|
322
|
+
if (noncode.size !== 4 || nodeProfile.publicCoverage.codeRecipeCount !== 23
|
|
323
|
+
|| nodeProfile.publicCoverage.noncodeProfileCount !== 4) {
|
|
324
|
+
throw new Error("Registered verifier route inventory is invalid");
|
|
325
|
+
}
|
|
326
|
+
const profile = installedJson(installedRoot, "adapters/node-typescript/profile.json", "Node profile");
|
|
327
|
+
const policy = installedJson(installedRoot, "packages/piagent-core/policies/base-policy.json", "base policy");
|
|
328
|
+
const approvedDockerSha256 = registeredMeasurement.payload.resources.verifiers
|
|
329
|
+
.find(item => item.id === "docker-runtime")?.sha256;
|
|
330
|
+
if (!HASH.test(String(approvedDockerSha256 ?? ""))) {
|
|
331
|
+
throw new Error("Registered Docker runtime identity is missing");
|
|
332
|
+
}
|
|
333
|
+
const planAssets = [], entries = [];
|
|
334
|
+
let dockerCommand = null;
|
|
335
|
+
for (const scenario of scenarios) {
|
|
336
|
+
const relativePath = `plans/${scenario.id}.json`, bytes = readRegisteredAsset(registeredMeasurement, relativePath);
|
|
337
|
+
let plan;
|
|
338
|
+
try { plan = JSON.parse(bytes); }
|
|
339
|
+
catch { throw new Error(`Registered verification plan is not JSON: ${scenario.id}`); }
|
|
340
|
+
registeredPlanForSurface(plan, "piagent");
|
|
341
|
+
registeredPlanForSurface(plan, "codex-cli");
|
|
342
|
+
const selectedDocker = plan.backend?.dockerCommand;
|
|
343
|
+
if (JSON.stringify(Object.keys(selectedDocker ?? {})) !== JSON.stringify(["path", "sha256"])
|
|
344
|
+
|| typeof selectedDocker.path !== "string" || !path.isAbsolute(selectedDocker.path)
|
|
345
|
+
|| path.normalize(selectedDocker.path) !== selectedDocker.path || selectedDocker.path.includes("\0")
|
|
346
|
+
|| selectedDocker.sha256 !== approvedDockerSha256) {
|
|
347
|
+
throw new Error(`Registered Docker command binding is invalid: ${scenario.id}`);
|
|
348
|
+
}
|
|
349
|
+
let observedDocker;
|
|
350
|
+
try { observedDocker = benchmarkCommandIdentity(selectedDocker.path, { fullPackageClosure: false }); }
|
|
351
|
+
catch { throw new Error(`Registered Docker command is unavailable: ${scenario.id}`); }
|
|
352
|
+
if (observedDocker.resolvedPath !== selectedDocker.path
|
|
353
|
+
|| observedDocker.contentDigest !== selectedDocker.sha256 || observedDocker.executable !== true) {
|
|
354
|
+
throw new Error(`Registered Docker command changed: ${scenario.id}`);
|
|
355
|
+
}
|
|
356
|
+
if (dockerCommand && JSON.stringify(dockerCommand) !== JSON.stringify(selectedDocker)) {
|
|
357
|
+
throw new Error("Registered plans disagree on the Docker command identity");
|
|
358
|
+
}
|
|
359
|
+
dockerCommand = freeze({ path: selectedDocker.path, sha256: selectedDocker.sha256 });
|
|
360
|
+
const input = inputs.get(scenario.id), receipt = benchmarkVerificationReceiptForTurn(input.selected, { profile, policy });
|
|
361
|
+
if (plan.schemaVersion !== 3 || plan.operatorRequestDigest !== benchmarkVerificationRequestDigest(input.selected)
|
|
362
|
+
|| plan.backend.imageId !== nodeProfile.workerImage.id
|
|
363
|
+
|| plan.contracts.length !== receipt.criteria.length) {
|
|
364
|
+
throw new Error(`Registered verification plan does not match its primary request: ${scenario.id}`);
|
|
365
|
+
}
|
|
366
|
+
const expectedRoute = noncode.has(scenario.id) ? "composite" : "code";
|
|
367
|
+
for (const [index, contract] of plan.contracts.entries()) {
|
|
368
|
+
const criterion = receipt.criteria[index];
|
|
369
|
+
if (contract.route !== expectedRoute || contract.criterionId !== criterion.criterionId
|
|
370
|
+
|| contract.criterionHash !== criterion.criterionHash) {
|
|
371
|
+
throw new Error(`Registered verification criterion does not match runtime intake: ${scenario.id}`);
|
|
372
|
+
}
|
|
373
|
+
if (contract.route === "composite") {
|
|
374
|
+
const identity = contract.planContext.identity;
|
|
375
|
+
if (!exact(identity, ["suiteDigest", "configDigest", "armDigests"])
|
|
376
|
+
|| !exact(identity.armDigests, ["piagent", "codex-cli"])
|
|
377
|
+
|| ![identity.suiteDigest, identity.configDigest, identity.armDigests.piagent,
|
|
378
|
+
identity.armDigests["codex-cli"]].every(value => HASH.test(value))) {
|
|
379
|
+
throw new Error(`Registered composite arm identities are incomplete: ${scenario.id}`);
|
|
380
|
+
}
|
|
381
|
+
const publicContract = JSON.parse(contract.planContext.contractText);
|
|
382
|
+
if (publicContract.criterionIndex !== index || publicContract.criterionId !== criterion.criterionId
|
|
383
|
+
|| publicContract.criterionHash !== criterion.criterionHash
|
|
384
|
+
|| publicContract.criterionText !== criterion.criterionText) {
|
|
385
|
+
throw new Error(`Registered composite criterion text does not match runtime intake: ${scenario.id}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
planAssets.push(Object.freeze({ path: relativePath, sha256: hash(bytes), bytes: bytes.length }));
|
|
390
|
+
entries.push(Object.freeze({ scenarioId: scenario.id, plans: [freeze(plan)] }));
|
|
391
|
+
}
|
|
392
|
+
const boundAssets = [
|
|
393
|
+
{ path: "catalog.json", sha256: hash(catalogBytes), bytes: catalogBytes.length },
|
|
394
|
+
{ path: "measurement/node-workload-api-v1.json", sha256: hash(nodeBytes), bytes: nodeBytes.length },
|
|
395
|
+
...registeredMeasurement.payload.promptRolesChanged.map(id => {
|
|
396
|
+
const relativePath = `measurement/prompts/${id}.md`,
|
|
397
|
+
inventory = registeredMeasurement.inventory.entries.find(item => item.path === relativePath);
|
|
398
|
+
return { path: relativePath, sha256: inventory.sha256, bytes: inventory.bytes };
|
|
399
|
+
}),
|
|
400
|
+
...planAssets
|
|
401
|
+
];
|
|
402
|
+
const contentDigest = hash(JSON.stringify(boundAssets)), catalog = freeze({
|
|
403
|
+
schemaVersion: 2, kind: NODE_BENCHMARK_VERIFICATION_PLAN_VERSION,
|
|
404
|
+
suiteDigest, verifierDigest, scenarios: entries
|
|
405
|
+
});
|
|
406
|
+
const identity = freeze({ kind: catalog.kind, contentDigest, suiteDigest, verifierDigest,
|
|
407
|
+
scenarios: entries.map(entry => ({ scenarioId: entry.scenarioId,
|
|
408
|
+
requests: entry.plans.map(plan => ({ operatorRequestDigest: plan.operatorRequestDigest,
|
|
409
|
+
criterionCount: plan.contracts.length, criteria: plan.contracts.map(contract => ({
|
|
410
|
+
criterionId: contract.criterionId, criterionHash: contract.criterionHash
|
|
411
|
+
})) })) })) });
|
|
412
|
+
const isCurrent = () => {
|
|
413
|
+
try {
|
|
414
|
+
return installedContractVerifierDigest(installedRoot) === verifierDigest
|
|
415
|
+
&& boundAssets.every(asset => hash(readRegisteredAsset(registeredMeasurement, asset.path)) === asset.sha256);
|
|
416
|
+
} catch { return false; }
|
|
417
|
+
};
|
|
418
|
+
if (!dockerCommand) throw new Error("Registered Docker command binding is unavailable");
|
|
419
|
+
return Object.freeze({ identity, isCurrent, dockerCommand,
|
|
420
|
+
registeredSuiteId: registeredMeasurement.payload.suiteId,
|
|
421
|
+
measurementConfigurationDigest: registeredMeasurement.payload.sharedEnvironmentDigest,
|
|
422
|
+
registeredInput(scenarioId) {
|
|
423
|
+
if (!isCurrent()) throw new Error("Registered measurement input or verifier changed");
|
|
424
|
+
return inputs.get(scenarioId) ?? null;
|
|
425
|
+
},
|
|
426
|
+
prepare({ scenarioId, surface, projectRoot, directory, approved = false }) {
|
|
427
|
+
if (surface !== "piagent") return null;
|
|
428
|
+
if (approved !== true) throw new Error("Registered benchmark verification is not approved");
|
|
429
|
+
if (!isCurrent()) throw new Error("Registered benchmark verification changed");
|
|
430
|
+
const entry = entries.find(item => item.scenarioId === scenarioId);
|
|
431
|
+
if (!entry) return Object.freeze({ environment: Object.freeze({}), observe: () => freeze({ schemaVersion: 1,
|
|
432
|
+
planDigest: contentDigest, status: "not-configured", attempts: 0, workersObserved: 0, requests: [] }) });
|
|
433
|
+
const plans = entry.plans.map(plan => registeredPlanForSurface(plan, surface));
|
|
434
|
+
const { configPath } = writeHostContractApproval({
|
|
435
|
+
directory, projectRoot, installedRoot, plans, approved: true
|
|
436
|
+
});
|
|
437
|
+
return Object.freeze({ environment: Object.freeze({ PIAGENT_INDEPENDENT_VERIFICATION_CONFIG: configPath }),
|
|
438
|
+
observe(tasks) { return observeRequests({ configPath, projectRoot, installedRoot, plans,
|
|
439
|
+
planDigest: contentDigest, tasks, isCurrent }); } });
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function readPlan(file) {
|
|
445
|
+
if (!path.isAbsolute(file) || fs.realpathSync.native(file) !== file) throw new Error("Verification plan path must be canonical");
|
|
446
|
+
const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
447
|
+
try {
|
|
448
|
+
const stat = fs.fstatSync(fd);
|
|
449
|
+
if (!stat.isFile() || stat.nlink !== 1 || stat.uid !== process.getuid() || (stat.mode & 0o077) !== 0
|
|
450
|
+
|| stat.size < 1 || stat.size > 2 * 1024 * 1024) throw new Error("Verification plan must be a private bounded host file");
|
|
451
|
+
const bytes = fs.readFileSync(fd), after = fs.fstatSync(fd), current = fs.lstatSync(file);
|
|
452
|
+
if (bytes.length !== stat.size || current.isSymbolicLink()
|
|
453
|
+
|| ["dev", "ino", "size", "mode", "nlink", "mtimeMs", "ctimeMs"].some(key => stat[key] !== after[key] || stat[key] !== current[key])) {
|
|
454
|
+
throw new Error("Verification plan changed during read");
|
|
455
|
+
}
|
|
456
|
+
return bytes;
|
|
457
|
+
} finally { fs.closeSync(fd); }
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/** Structural validation is not operator approval or source/plan authentication. */
|
|
461
|
+
export function validateBenchmarkVerificationPlan(value) {
|
|
462
|
+
const nodeProfile = value?.schemaVersion === 2 && value?.kind === NODE_BENCHMARK_VERIFICATION_PLAN_VERSION;
|
|
463
|
+
if (!exact(value, ["schemaVersion", "kind", "suiteDigest", "verifierDigest", "scenarios"])
|
|
464
|
+
|| !nodeProfile && (value.schemaVersion !== 1 || value.kind !== BENCHMARK_VERIFICATION_PLAN_VERSION)
|
|
465
|
+
|| !HASH.test(value.suiteDigest) || !HASH.test(value.verifierDigest)
|
|
466
|
+
|| !Array.isArray(value.scenarios) || value.scenarios.length < 1 || value.scenarios.length > 100) {
|
|
467
|
+
throw new TypeError("Invalid benchmark verification catalog");
|
|
468
|
+
}
|
|
469
|
+
const seen = new Set();
|
|
470
|
+
for (const entry of value.scenarios) {
|
|
471
|
+
if (!exact(entry, ["scenarioId", "plans"]) || typeof entry.scenarioId !== "string"
|
|
472
|
+
|| !/^[a-z0-9][a-z0-9._-]{0,79}$/.test(entry.scenarioId) || seen.has(entry.scenarioId)) {
|
|
473
|
+
throw new TypeError("Invalid or duplicate verification scenario");
|
|
474
|
+
}
|
|
475
|
+
seen.add(entry.scenarioId);
|
|
476
|
+
validateHostContractPlan({ schemaVersion: nodeProfile ? 4 : 2, plans: entry.plans });
|
|
477
|
+
}
|
|
478
|
+
return value;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** Read and bind operator-authored expected results; never derive them from a candidate or grader. */
|
|
482
|
+
export function loadBenchmarkVerificationPlan({ file, installedRoot, suiteDigest, scenarios, suiteRoot, resolveSuiteEntry }) {
|
|
483
|
+
if (inside(installedRoot, file) || inside(suiteRoot, file)) throw new Error("Verification catalog must be outside candidate and suite source");
|
|
484
|
+
const bytes = readPlan(file), value = validateBenchmarkVerificationPlan(JSON.parse(bytes));
|
|
485
|
+
if (value.suiteDigest !== suiteDigest || value.verifierDigest !== installedContractVerifierDigest(installedRoot)) {
|
|
486
|
+
throw new Error("Verification plan does not match the frozen suite and installed verifier");
|
|
487
|
+
}
|
|
488
|
+
const known = new Map(scenarios.map(scenario => [scenario.id, scenario]));
|
|
489
|
+
for (const entry of value.scenarios) {
|
|
490
|
+
const scenario = known.get(entry.scenarioId);
|
|
491
|
+
if (!scenario) throw new Error("Unknown verification scenario");
|
|
492
|
+
// Piagent journeys dispatch workflow metadata before automatic intake.
|
|
493
|
+
// Baseline surfaces receive no approval and keep their own raw turn text.
|
|
494
|
+
const turns = resolvedJourneyTurns(scenario, suiteRoot, resolveSuiteEntry) ?? [{ message: fs.readFileSync(
|
|
495
|
+
resolveSuiteEntry(suiteRoot, scenario.prompt, "verification public prompt"), "utf8").trim() }];
|
|
496
|
+
const requests = new Map();
|
|
497
|
+
for (const turn of turns) {
|
|
498
|
+
const digest = benchmarkVerificationRequestDigest(turn), source = JSON.stringify([turn.workflow ?? null, turn.message]);
|
|
499
|
+
if (requests.has(digest) && requests.get(digest) !== source) throw new Error("Ambiguous verification request identity after normalization");
|
|
500
|
+
requests.set(digest, source);
|
|
501
|
+
}
|
|
502
|
+
if (entry.plans.some(plan => !requests.has(plan.operatorRequestDigest))) throw new Error("Verification plan authorizes a request not sent by this scenario");
|
|
503
|
+
}
|
|
504
|
+
const catalog = freeze(value);
|
|
505
|
+
const identity = freeze({ kind: catalog.kind, contentDigest: hash(bytes),
|
|
506
|
+
suiteDigest, verifierDigest: catalog.verifierDigest,
|
|
507
|
+
scenarios: catalog.scenarios.map(entry => ({ scenarioId: entry.scenarioId,
|
|
508
|
+
requests: entry.plans.map(plan => ({ operatorRequestDigest: plan.operatorRequestDigest, criterionCount: plan.contracts.length,
|
|
509
|
+
criteria: plan.contracts.map(contract => ({ criterionId: contract.criterionId, criterionHash: contract.criterionHash })) })) })) });
|
|
510
|
+
const isCurrent = () => {
|
|
511
|
+
try { return hash(readPlan(file)) === identity.contentDigest && installedContractVerifierDigest(installedRoot) === identity.verifierDigest; }
|
|
512
|
+
catch { return false; }
|
|
513
|
+
};
|
|
514
|
+
return Object.freeze({ identity, isCurrent,
|
|
515
|
+
prepare({ scenarioId, surface, projectRoot, directory, approved = false }) {
|
|
516
|
+
if (surface !== "piagent") return null;
|
|
517
|
+
if (approved !== true) throw new Error("Benchmark verification requires explicit --approve-verification");
|
|
518
|
+
if (inside(projectRoot, file)) throw new Error("Verification catalog must be outside the candidate project");
|
|
519
|
+
if (!isCurrent()) throw new Error("Frozen benchmark verification plan or verifier changed");
|
|
520
|
+
const entry = catalog.scenarios.find(item => item.scenarioId === scenarioId);
|
|
521
|
+
if (!entry) return Object.freeze({ environment: Object.freeze({}), observe: () => freeze({ schemaVersion: 1,
|
|
522
|
+
planDigest: identity.contentDigest, status: "not-configured", attempts: 0, workersObserved: 0, requests: [] }) });
|
|
523
|
+
const { configPath } = writeHostContractApproval({ directory, projectRoot, installedRoot, plans: entry.plans, approved: true });
|
|
524
|
+
return Object.freeze({ environment: Object.freeze({ PIAGENT_INDEPENDENT_VERIFICATION_CONFIG: configPath }),
|
|
525
|
+
observe(tasks) { return observeRequests({ configPath, projectRoot, installedRoot, plans: entry.plans,
|
|
526
|
+
planDigest: identity.contentDigest, tasks, isCurrent }); } });
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** Observation only, never completion authority. Keep failures and pending attempts in the denominator. */
|
|
532
|
+
function observeRequests({ configPath, projectRoot, installedRoot, plans, planDigest, tasks, isCurrent }) {
|
|
533
|
+
let config;
|
|
534
|
+
try {
|
|
535
|
+
if (!isCurrent()) throw new Error("Plan drift");
|
|
536
|
+
if (!Array.isArray(tasks) || tasks.length > 1000 || tasks.some(task => typeof task?.taskRunId !== "string")
|
|
537
|
+
|| new Set(tasks.map(task => task.taskRunId)).size !== tasks.length) throw new Error("Invalid task observation");
|
|
538
|
+
config = openHostContractConfiguration({ configPath, projectRoot, installedRoot });
|
|
539
|
+
let attempts = 0, workersObserved = 0, complete = true;
|
|
540
|
+
const requests = plans.map(plan => {
|
|
541
|
+
const matched = tasks.filter(task => task.operatorRequestDigest === plan.operatorRequestDigest);
|
|
542
|
+
if (matched.length === 0) complete = false;
|
|
543
|
+
const nodeProfile = plan.schemaVersion === 3;
|
|
544
|
+
const profile = nodeProfile ? plan.backend.profile : undefined;
|
|
545
|
+
const templateFor = contract => compileIndependentContract(JSON.stringify({ schemaVersion: nodeProfile ? 2 : 1,
|
|
546
|
+
...(nodeProfile ? { profile } : {}), source: "export const placeholder=0;", exportName: contract.exportName, checks: contract.checks }));
|
|
547
|
+
const codeContract = plan.contracts.find(contract => contract.route !== "composite");
|
|
548
|
+
const compilerVersion = codeContract ? templateFor(codeContract).version : null;
|
|
549
|
+
const backendDigest = compilerVersion ? hash(JSON.stringify([DURABLE_EXECUTION_VERSION, compilerVersion,
|
|
550
|
+
EXECUTION_SNAPSHOT_VERSION, plan.backend.imageId, plan.backend.dockerSocket,
|
|
551
|
+
plan.backend.dockerCommand, plan.backend.timeoutMs, profile ?? null,
|
|
552
|
+
...(plan.backend.startupAllowanceMs ? [plan.backend.startupAllowanceMs] : [])])) : null;
|
|
553
|
+
const publicationStore = plan.contracts.some(contract => contract.route === "composite")
|
|
554
|
+
? config.withCompositeRecovery(({ key, directory, projectRoot: approvedRoot }) =>
|
|
555
|
+
openCompositeTaskPublicationStore({ key, directory, projectRoot: approvedRoot })) : null;
|
|
556
|
+
const runs = matched.map(task => ({ taskRunId: task.taskRunId, criteria: plan.contracts.map(contract => {
|
|
557
|
+
if (contract.route === "composite") {
|
|
558
|
+
const result = { criterionId: contract.criterionId, criterionHash: contract.criterionHash,
|
|
559
|
+
attempts: 0, phase: "not-observed", verdict: null, workerObserved: false };
|
|
560
|
+
if (!publicationStore || typeof task.sessionId !== "string") { complete = false; return result; }
|
|
561
|
+
const record = publicationStore.read(task.taskRunId, task.sessionId);
|
|
562
|
+
if (!record) { complete = false; return result; }
|
|
563
|
+
result.attempts = 1; attempts += 1;
|
|
564
|
+
const matching = task.acceptanceReceipt?.criteria.some(criterion =>
|
|
565
|
+
criterion.id === contract.criterionId && criterion.hash === contract.criterionHash);
|
|
566
|
+
const entry = record.entries.find(item => item.criterionId === contract.criterionId);
|
|
567
|
+
const taskDigest = compositeTaskPublicationDigest(task);
|
|
568
|
+
const taskBound = task.trace?.outcome === "completed"
|
|
569
|
+
? taskDigest === record.terminalTaskDigest : taskDigest === record.pendingTaskDigest;
|
|
570
|
+
if (!matching || !entry || entry.criterionHash !== contract.criterionHash
|
|
571
|
+
|| record.operatorRequestDigest !== plan.operatorRequestDigest || !taskBound) {
|
|
572
|
+
complete = false; result.phase = "binding-mismatch"; return result;
|
|
573
|
+
}
|
|
574
|
+
const status = publicationStore.inspect(record).statuses.find(item =>
|
|
575
|
+
item.criterionId === contract.criterionId)?.status;
|
|
576
|
+
if (status !== "task-completed" || task.trace?.outcome !== "completed") {
|
|
577
|
+
complete = false; result.phase = "reserved"; return result;
|
|
578
|
+
}
|
|
579
|
+
result.phase = "settled"; result.verdict = "pass";
|
|
580
|
+
// The legacy field name is retained for report compatibility. Here it
|
|
581
|
+
// means the host observer re-opened a signed, fully settled composite
|
|
582
|
+
// publication; it does not claim that a code worker ran.
|
|
583
|
+
result.workerObserved = true; workersObserved += 1;
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
const event = config.store.latest({ taskRunId: task.taskRunId, criterionId: contract.criterionId });
|
|
587
|
+
const result = { criterionId: contract.criterionId, criterionHash: contract.criterionHash,
|
|
588
|
+
attempts: event?.attempt ?? 0, phase: event?.phase ?? "not-observed", verdict: null, workerObserved: false };
|
|
589
|
+
attempts += result.attempts;
|
|
590
|
+
const matching = task.acceptanceReceipt?.criteria.some(criterion => criterion.id === contract.criterionId && criterion.hash === contract.criterionHash);
|
|
591
|
+
if (!matching || !event || event.binding.criterionHash !== contract.criterionHash
|
|
592
|
+
|| event.binding.verifierDigest !== config.payload.verifierDigest || event.binding.backendDigest !== backendDigest) {
|
|
593
|
+
complete = false; result.phase = event ? "binding-mismatch" : "not-observed"; return result;
|
|
594
|
+
}
|
|
595
|
+
if (event.phase !== "settled") { complete = false; return result; }
|
|
596
|
+
const evidence = JSON.parse(event.evidenceText);
|
|
597
|
+
if (evidence.version !== DURABLE_EXECUTION_VERSION || evidence.snapshotDigest !== event.binding.snapshotDigest
|
|
598
|
+
|| evidence.planDigest !== event.binding.planDigest || !["pass", "fail", "unknown", "error"].includes(evidence.verdict)) {
|
|
599
|
+
complete = false; result.phase = "invalid-evidence"; return result;
|
|
600
|
+
}
|
|
601
|
+
result.verdict = evidence.verdict;
|
|
602
|
+
const observed = evidence.observed, execution = observed?.result?.execution;
|
|
603
|
+
const template = templateFor(contract);
|
|
604
|
+
if (observed?.snapshotDigest === event.binding.snapshotDigest && observed.result?.version === template.version
|
|
605
|
+
&& observed.result.planDigest === event.binding.planDigest && execution?.runId === event.attemptId
|
|
606
|
+
&& execution.imageId === plan.backend.imageId && HASH.test(execution.sourceDigest) && HASH.test(execution.requestDigest)
|
|
607
|
+
&& execution.observation && execution.cleanupConfirmed === true) {
|
|
608
|
+
const response = parseResponse(JSON.stringify(execution.observation), parseRequest(template.requestText), execution.requestDigest);
|
|
609
|
+
const compared = compareIndependentExecution({ ...template, planDigest: event.binding.planDigest }, execution);
|
|
610
|
+
result.workerObserved = response.status === execution.status && compared.verdict === evidence.verdict
|
|
611
|
+
&& compared.verdict === observed.verdict && compared.verdict === observed.result.verdict
|
|
612
|
+
&& JSON.stringify(compared.checks) === JSON.stringify(observed.result.checks)
|
|
613
|
+
&& JSON.stringify(compared.counterexamples) === JSON.stringify(observed.result.counterexamples);
|
|
614
|
+
}
|
|
615
|
+
if (result.workerObserved) workersObserved += 1;
|
|
616
|
+
else complete = false;
|
|
617
|
+
return result;
|
|
618
|
+
}) }));
|
|
619
|
+
return { operatorRequestDigest: plan.operatorRequestDigest, runs };
|
|
620
|
+
});
|
|
621
|
+
if (!config.isCurrent() || !isCurrent()) throw new Error("Approval drift");
|
|
622
|
+
return freeze({ schemaVersion: 1, planDigest, status: complete ? "observed" : "partial", attempts, workersObserved, requests });
|
|
623
|
+
} catch {
|
|
624
|
+
// Usage has already been collected by the caller. Invalid verification
|
|
625
|
+
// evidence must not discard the paid attempt or reveal private plan data.
|
|
626
|
+
return freeze({ schemaVersion: 1, planDigest, status: "unavailable", attempts: null, workersObserved: null, requests: [] });
|
|
627
|
+
} finally { config?.close(); }
|
|
628
|
+
}
|