diff --git a/.bitcode/v34-deployment-host-capability-catalog.json b/.bitcode/v34-deployment-host-capability-catalog.json index 175bc152a..798f534da 100644 --- a/.bitcode/v34-deployment-host-capability-catalog.json +++ b/.bitcode/v34-deployment-host-capability-catalog.json @@ -360,7 +360,7 @@ ] }, { - "digest": "sha256:fa2d5f781b1c7ac6d5466972471406ebedc998b25384a9edfcc68954e8cf3125", + "digest": "sha256:82edb3ca798a13834379748430690382cfb38bb9f7489e5a180986431abfdff4", "relativePath": "BITCODE_SPEC_V34.md", "requiredTokens": [ { diff --git a/.bitcode/v34-distributed-execution-runtime-receipts.json b/.bitcode/v34-distributed-execution-runtime-receipts.json new file mode 100644 index 000000000..b8ffaa756 --- /dev/null +++ b/.bitcode/v34-distributed-execution-runtime-receipts.json @@ -0,0 +1,448 @@ +{ + "artifactId": "v34-distributed-execution-runtime-receipts", + "closureCommand": "pnpm run check:v34-gate3", + "coverage": { + "credentialsSerialized": false, + "databaseProjectionRootsCovered": true, + "inputRootsCovered": true, + "ledgerProjectionRootsCovered": true, + "logRootsCovered": true, + "missingWorkKinds": [], + "objectStorageRootsCovered": true, + "observedWorkKinds": [ + "ledger_operation", + "object_storage_write", + "pipeline_run", + "proof_generation", + "ptrr_agent", + "repair_job", + "thricified_generation", + "tool_call", + "wallet_operation" + ], + "outputRootsCovered": true, + "proofRootsCovered": true, + "protectedSourceVisible": false, + "ptrrAgentReceiptCovered": true, + "repairPostureCovered": true, + "requestResponseCompletionRequired": false, + "routeHandlerRequiresSynchronousCompletion": false, + "thricifiedGenerationReceiptCovered": true, + "toolCallReceiptCovered": true, + "walletOperationRootsCovered": true, + "workKindCount": 9 + }, + "currentTarget": "V33", + "generatedAt": "2026-05-22T00:00:00.000Z", + "passed": true, + "receiptCatalogRoot": "v34-distributed-execution-runtime-receipts:42ecee4ea50c8e788ea07f34", + "receipts": [ + { + "commandOrPipelineId": "ReadFitsFindingSynthesis", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-read-fits-finding-synthesis", + "hostId": "pipeline_workers", + "inputRoot": "sha256:pipeline-input-root", + "laneId": "staging-testnet", + "ledgerProjectionRoot": "sha256:pipeline-ledger-projection-root", + "logRoot": "sha256:runtime-log-root", + "objectStorageRoot": "sha256:pipeline-object-storage-root", + "outputRoot": "sha256:pipeline-output-root", + "phaseId": "discovery", + "proofRoot": "sha256:pipeline-proof-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:430ccd2b514dfc142a520af3", + "repairPosture": "retry-detached-pipeline-from-input-root", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "workKind": "pipeline_run" + }, + { + "agentId": "ReadFitsFindingSynthesisDiscoveryAgent", + "commandOrPipelineId": "ReadFitsFindingSynthesisDiscoveryAgent", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-read-fits-agent", + "hostId": "pipeline_workers", + "inputRoot": "sha256:agent-input-root", + "laneId": "staging-testnet", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:agent-output-root", + "parentReceiptRoot": "receipt:pipeline-run-root", + "phaseId": "discovery", + "proofRoot": "sha256:agent-proof-root", + "protectedSourceVisible": false, + "ptrrStep": "plan", + "receiptRoot": "v34-distributed-execution-runtime-receipt:d12c0609544a666b7fd39d56", + "repairPosture": "resume-ptrr-agent-from-step-root", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "workKind": "ptrr_agent" + }, + { + "agentId": "ReadFitsFindingSynthesisDiscoveryAgent", + "commandOrPipelineId": "ReadFitsFindingSynthesisDiscoveryAgent.plan.reason", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-thricified-generation", + "hostId": "pipeline_workers", + "inputRoot": "sha256:generation-input-root", + "laneId": "staging-testnet", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:generation-output-root", + "parentReceiptRoot": "receipt:ptrr-agent-root", + "phaseId": "discovery", + "proofRoot": "sha256:generation-proof-root", + "protectedSourceVisible": false, + "ptrrStep": "plan", + "receiptRoot": "v34-distributed-execution-runtime-receipt:659242c128b93f08f0575ff2", + "repairPosture": "regenerate-from-redacted-prompt-and-context-root", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "thricifiedGenerationStep": "reason", + "workKind": "thricified_generation" + }, + { + "agentId": "ReadFitsFindingSynthesisDiscoveryAgent", + "commandOrPipelineId": "AssetPackLexicalDepositorySearchTool", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-depository-search-tool", + "hostId": "pipeline_workers", + "inputRoot": "sha256:tool-input-root", + "laneId": "staging-testnet", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:tool-output-root", + "parentReceiptRoot": "receipt:thricified-generation-root", + "phaseId": "discovery", + "proofRoot": "sha256:tool-proof-root", + "protectedSourceVisible": false, + "ptrrStep": "try", + "receiptRoot": "v34-distributed-execution-runtime-receipt:995d39060db5d4e6fcad326c", + "repairPosture": "rerun-tool-from-input-root-with-source-safe-query", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "toolId": "AssetPackLexicalDepositorySearchTool", + "workKind": "tool_call" + }, + { + "commandOrPipelineId": "ledger.project.read-rights", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-ledger-operation", + "hostId": "ledger_projection", + "inputRoot": "sha256:ledger-input-root", + "laneId": "staging-testnet", + "ledgerProjectionRoot": "sha256:ledger-projection-root", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:ledger-output-root", + "proofRoot": "sha256:ledger-proof-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:5f244afaf444fee8c8519e65", + "repairPosture": "hold-unlock-and-replay-ledger-projection", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "workKind": "ledger_operation" + }, + { + "commandOrPipelineId": "btc.fee.sign-and-broadcast", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-wallet-operation", + "hostId": "ledger_broadcasters", + "inputRoot": "sha256:wallet-input-root", + "laneId": "signet", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:wallet-output-root", + "proofRoot": "sha256:wallet-proof-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:02f8b9a62a3bb6b09423c448", + "repairPosture": "deny-broadcast-until-wallet-policy-repaired", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "walletOperationRoot": "sha256:wallet-operation-root", + "workKind": "wallet_operation" + }, + { + "commandOrPipelineId": "deployment.proof.generate", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-proof-generation", + "hostId": "proof_services", + "inputRoot": "sha256:proof-input-root", + "laneId": "staging-testnet", + "logRoot": "sha256:runtime-log-root", + "outputRoot": "sha256:proof-output-root", + "proofRoot": "sha256:proof-generation-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:1acfe1bd40c8186af4bda502", + "repairPosture": "regenerate-proof-from-canonical-inputs", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "workKind": "proof_generation" + }, + { + "commandOrPipelineId": "assetpack.preview.persist", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-object-storage-write", + "hostId": "object_storage", + "inputRoot": "sha256:object-storage-input-root", + "laneId": "staging-testnet", + "logRoot": "sha256:runtime-log-root", + "objectStorageRoot": "sha256:object-storage-root", + "outputRoot": "sha256:object-storage-output-root", + "proofRoot": "sha256:object-storage-proof-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:878d86f70a8e0d7afd9e0578", + "repairPosture": "lock-delivery-and-rewrite-from-authorized-artifact-root", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "succeeded", + "workKind": "object_storage_write" + }, + { + "commandOrPipelineId": "projection.repair", + "completedAt": "2026-05-22T00:00:01.000Z", + "credentialsSerialized": false, + "databaseProjectionRoot": "sha256:database-projection-root", + "executionId": "execution-repair-job", + "hostId": "repair_jobs", + "inputRoot": "sha256:repair-input-root", + "laneId": "staging-testnet", + "ledgerProjectionRoot": "sha256:repair-ledger-projection-root", + "logRoot": "sha256:runtime-log-root", + "objectStorageRoot": "sha256:repair-object-storage-root", + "outputRoot": "sha256:repair-output-root", + "proofRoot": "sha256:repair-proof-root", + "protectedSourceVisible": false, + "receiptRoot": "v34-distributed-execution-runtime-receipt:720dd7faab2534cd345af2cb", + "repairPosture": "repair-complete-with-replayable-proof-root", + "replayCommand": "pnpm run check:v34-gate3", + "routeHandlerBoundary": "request_response_not_required", + "sourceSafety": { + "containsProtectedSource": false, + "containsSecret": false, + "credentialsSerialized": false, + "protectedSourceVisible": false, + "sourceSafe": true + }, + "startedAt": "2026-05-22T00:00:00.000Z", + "status": "repaired", + "workKind": "repair_job" + } + ], + "requiredWorkKinds": [ + "pipeline_run", + "ptrr_agent", + "thricified_generation", + "tool_call", + "ledger_operation", + "wallet_operation", + "proof_generation", + "object_storage_write", + "repair_job" + ], + "schemaId": "bitcode.v34.distributedExecutionRuntimeReceipts.v1", + "sharedFixtureFiles": [ + "packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts", + "packages/pipeline-hosts/src/index.ts", + "BITCODE_SPEC_V34.md", + "BITCODE_SPEC_V34_DELTA.md", + "BITCODE_SPEC_V34_PARITY_MATRIX.md", + "packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts", + "scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs" + ], + "sourceEvidence": [ + { + "digest": "sha256:40ed8d6b9d92e1d7f69fcca037b0b8c419e3d7ca045c1cb4669e52e1b6b0cdbb", + "relativePath": "packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts", + "requiredTokens": [ + { + "present": true, + "token": "DistributedExecutionRuntimeReceipt" + }, + { + "present": true, + "token": "DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS" + }, + { + "present": true, + "token": "request_response_not_required" + }, + { + "present": true, + "token": "ptrr_agent" + }, + { + "present": true, + "token": "thricified_generation" + }, + { + "present": true, + "token": "object_storage_write" + }, + { + "present": true, + "token": "repair_job" + } + ] + }, + { + "digest": "sha256:baad6be2b6f92cdf9f5b23bfba513bff837d4c6ab7f86d57336fab6cda6be455", + "relativePath": "packages/pipeline-hosts/src/index.ts", + "requiredTokens": [ + { + "present": true, + "token": "distributed-execution-runtime-receipt" + } + ] + }, + { + "digest": "sha256:82edb3ca798a13834379748430690382cfb38bb9f7489e5a180986431abfdff4", + "relativePath": "BITCODE_SPEC_V34.md", + "requiredTokens": [ + { + "present": true, + "token": ".bitcode/v34-distributed-execution-runtime-receipts.json" + }, + { + "present": true, + "token": "DistributedExecutionRuntimeReceipt" + }, + { + "present": true, + "token": "request_response_not_required" + } + ] + } + ], + "sourceSafetyVerdict": "source-safe-distributed-execution-runtime-receipts", + "testEvidence": [ + { + "digest": "sha256:63733d5998d39900f7296ed25e183c42d715f4787a2d6cd47781c71bfa0fb3f9", + "relativePath": "packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts", + "requiredTokens": [ + { + "present": true, + "token": "catalogs pipeline runs, PTRR agents, ThricifiedGenerations, tool calls, ledger operations, wallet operations, proof generation, object-storage writes, and repair jobs" + }, + { + "present": true, + "token": "keeps long-running runtime work detached from request/response route handler completion" + }, + { + "present": true, + "token": "covers required roots for pipeline, tool, ledger, wallet, proof, storage, and repair receipts" + }, + { + "present": true, + "token": "fails closed when successful runtime receipts omit output roots" + }, + { + "present": true, + "token": "fails closed on secret-shaped or protected-source receipt text" + } + ] + }, + { + "digest": "sha256:1377b7006e67291bfaf6d03997a886a384ca3a0721cc27ebb721828ea13a7fd9", + "relativePath": "scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs", + "requiredTokens": [ + { + "present": true, + "token": "check:v34-distributed-execution-runtime-receipts" + }, + { + "present": true, + "token": "distributed-execution-runtime-receipt.test.ts" + }, + { + "present": true, + "token": "Distributed Execution Runtime Contracts" + } + ] + } + ], + "version": "V34" +} diff --git a/.bitcode/v34-environment-lane-contracts.json b/.bitcode/v34-environment-lane-contracts.json index f5d2d983a..68d7a8dbb 100644 --- a/.bitcode/v34-environment-lane-contracts.json +++ b/.bitcode/v34-environment-lane-contracts.json @@ -218,7 +218,7 @@ ] }, { - "digest": "sha256:ddbf849e72492008f814fde47e1c4ebf0565a445a579d01942cd543e18ff6b74", + "digest": "sha256:81211d9c1ac9db3b0c01ce07629c3c6170fbb3711a3ffefe0a52292c937196b8", "relativePath": "BITCODE_SPEC_V34_DELTA.md", "requiredTokens": [ { diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml index 0491fe04e..c47e15e72 100644 --- a/.github/workflows/bitcode-gate-quality.yml +++ b/.github/workflows/bitcode-gate-quality.yml @@ -149,6 +149,7 @@ jobs: node scripts/check-v33-gate10-promotion-readiness.mjs --promotion-mode --skip-branch-check node scripts/check-v34-gate1-deployment-roadmap-opening.mjs --skip-branch-check node scripts/check-v34-gate2-host-capability-environment-lanes.mjs --skip-branch-check + node scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs --skip-branch-check else echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2 exit 1 @@ -193,6 +194,7 @@ jobs: pnpm --dir packages/executions-mcp/src/mcp-server run test:mcp -- --runTestsByPath src/__tests__/unit/mcp-tool-contract.test.ts src/__tests__/unit/pipeline-ingress-contract.test.ts --runInBand pnpm --dir packages/chatgptapp exec jest --runTestsByPath src/__tests__/chatgpt-action-contract.test.ts src/__tests__/tools.test.ts --runInBand pnpm --filter @bitcode/pipeline-hosts exec jest --config jest.config.cjs --runTestsByPath src/__tests__/asset-pack-harness.test.ts --runInBand + pnpm --filter @bitcode/pipeline-hosts exec jest --config jest.config.cjs --runTestsByPath src/__tests__/distributed-execution-runtime-receipt.test.ts --runInBand pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --passWithNoTests --forceExit pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --runTestsByPath src/__tests__/reading-pipeline-observability.test.ts src/__tests__/reading-pipeline-contract.test.ts src/__tests__/v32-reading-pipeline-proof-coverage.test.ts --runInBand pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --runTestsByPath src/__tests__/asset-pack-disclosure.test.ts src/__tests__/postprocess.test.ts src/__tests__/read-need.test.ts --runInBand diff --git a/BITCODE_SPEC_V34.md b/BITCODE_SPEC_V34.md index 513276d2d..6467fad6e 100644 --- a/BITCODE_SPEC_V34.md +++ b/BITCODE_SPEC_V34.md @@ -3,12 +3,12 @@ ## Status - Version: `V34` -- V34 state: Gate 2 host capability and environment lane catalog is closed over promoted V33 canon +- V34 state: Gate 3 distributed execution runtime contracts are closed over promoted V33 canon - Current canonical/latest target: `V33` - Prior canonical anchor: `BITCODE_SPEC_V33.md` - Prior generated proof appendix: `BITCODE_SPEC_V33_PROVEN.md` -- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and later deployment-depth artifacts as gates close -- Source parity state: Gate 2 closes V34 host capability and environment lane parity; distributed execution, storage, approval, rollback, repair, and rehearsal source parity is not closed until the relevant gates close +- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, Gate 3 artifact `.bitcode/v34-distributed-execution-runtime-receipts.json`, and later deployment-depth artifacts as gates close +- Source parity state: Gate 3 closes V34 host capability, environment lane, and distributed execution runtime receipt parity; storage, approval, rollback, repair-job registry, rehearsal, and promotion source parity is not closed until the relevant gates close - Active canonical pointer during draft opening: `BITCODE_SPEC.txt` -> `V33` - Notes companion: `BITCODE_SPEC_V34_NOTES.md` - Delta companion: `BITCODE_SPEC_V34_DELTA.md` @@ -178,7 +178,7 @@ V34 adds deployment-facing contract objects over V33 protocol truth: - `DeploymentHostCapabilityCatalog`: host id, runtime surface, required packages, outbound network posture, secret requirements, storage carriers, observer/broadcaster capability, repair capability, proof output paths, and admission status. - `EnvironmentLaneContract`: lane id, supported Bitcoin network posture, Supabase/Vercel project posture, value-bearing admission, data-retention policy, wallet policy, secret scope, and proof requirements. -- `DistributedExecutionRuntimeReceipt`: execution id, host id, lane id, command or pipeline id, start/finish timestamps, input root, output root, log root, object-storage root, ledger/database projection roots, and repair posture. +- `DistributedExecutionRuntimeReceipt`: execution id, host id, lane id, work kind, command or pipeline id, start/finish timestamps, `routeHandlerBoundary`, input root, output root, log root, object-storage root, ledger/database projection roots, wallet operation root, proof root, PTRR agent fields, ThricifiedGeneration fields, tool id, and repair posture. Required work kinds are `pipeline_run`, `ptrr_agent`, `thricified_generation`, `tool_call`, `ledger_operation`, `wallet_operation`, `proof_generation`, `object_storage_write`, and `repair_job`; long-running work uses `request_response_not_required` rather than route-handler completion. - `DeploymentStoragePosture`: ledger-derived state, canonical database projection, object storage, proof artifacts, audit logs, rollback material, retention class, encryption posture, and repair command. - `MigrationApprovalGate`: migration id, schema diff root, generated type root, dry-run result, reviewer approval, rollback plan, and deployment lane admission. - `SecretRotationPlan`: secret family, storage owner, rotation cadence, rotation command, blast-radius note, proof root, and leak-response path. @@ -195,7 +195,7 @@ V34 closes through ten gates: 1. **Gate 1: V34 Deployment Roadmap And Spec Opening** opens the V34 family over V33 canon, updates `SPECIFICATIONS_ROADMAP.md`, documents V33 active / V34 draft posture, and wires `check:v34-gate1`. 2. **Gate 2: Host Capability And Environment Lane Catalog** inventories runtime hosts, services, queues, observers, broadcasters, storage carriers, and lanes through `DeploymentHostCapabilityCatalog` and `EnvironmentLaneContract`. It is closed by `packages/btd/src/deployment-host-capability-catalog.ts`, `.bitcode/v34-deployment-host-capability-catalog.json`, `.bitcode/v34-environment-lane-contracts.json`, `packages/btd/__tests__/deployment-host-capability-catalog.test.ts`, and `pnpm run check:v34-gate2`. -3. **Gate 3: Distributed Execution Runtime Contracts** defines `DistributedExecutionRuntimeReceipt` for long-running pipeline, ledger, wallet, proof, object-storage, and repair work. +3. **Gate 3: Distributed Execution Runtime Contracts** defines `DistributedExecutionRuntimeReceipt` for long-running pipeline, PTRR agent, ThricifiedGeneration, tool, ledger, wallet, proof, object-storage, and repair work. It is closed by `packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts`, `.bitcode/v34-distributed-execution-runtime-receipts.json`, `packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts`, and `pnpm run check:v34-gate3`. 4. **Gate 4: Ledger Database Object Storage Deployment Posture** hardens ledger-derived state, database projection, object storage, generated proof artifacts, audit logs, backup, retention, and rollback material. 5. **Gate 5: Secret Rotation And Credential Boundary Operations** defines secret families, storage owners, rotation commands, leak-response posture, CI masking, and runtime availability checks. 6. **Gate 6: Migration CI/CD Deployment Approval Gates** hardens schema migration approvals, generated type refresh, route scans, promotion commits, Vercel/Supabase lane checks, and deployment blockers. @@ -546,7 +546,7 @@ V34 preserves operator-quality proof output expectations and extends them to dep | `.bitcode/v34-canonical-input-report.json` | protocol | source-safe | `node scripts/check-bitcode-canonical-inputs.mjs --current-target V33` | | `.bitcode/v34-deployment-host-capability-catalog.json` | btd | source-safe-deployment-host-capability-metadata | `pnpm run check:v34-host-capability-environment-lanes` | | `.bitcode/v34-environment-lane-contracts.json` | btd | source-safe-environment-lane-contract-metadata | `pnpm run check:v34-host-capability-environment-lanes` | -| `.bitcode/v34-distributed-execution-runtime-receipts.json` | protocol | source-safe | later V34 gate | +| `.bitcode/v34-distributed-execution-runtime-receipts.json` | pipeline-hosts | source-safe-distributed-execution-runtime-receipts | `pnpm run check:v34-distributed-execution-runtime-receipts` | | `.bitcode/v34-deployment-storage-posture.json` | protocol | source-safe | later V34 gate | | `.bitcode/v34-secret-rotation-boundary-operations.json` | protocol | source-safe | later V34 gate | | `.bitcode/v34-migration-cicd-approval-gates.json` | protocol | source-safe | later V34 gate | @@ -559,6 +559,7 @@ V34 preserves operator-quality proof output expectations and extends them to dep Gate 1 requires `.bitcode/v34-spec-family-report.json` and `.bitcode/v34-canonical-input-report.json` to be declared. Gate 2 requires `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json` to be generated, source-safe, deterministic, and checked by `pnpm run check:v34-gate2`. +Gate 3 requires `.bitcode/v34-distributed-execution-runtime-receipts.json` to be generated, source-safe, deterministic, and checked by `pnpm run check:v34-gate3`, with receipt coverage for `pipeline_run`, `ptrr_agent`, `thricified_generation`, `tool_call`, `ledger_operation`, `wallet_operation`, `proof_generation`, `object_storage_write`, and `repair_job`. Later V34 gates introduce the remaining deployment artifacts listed above. ### Shared generated-artifact fields @@ -586,6 +587,7 @@ Canonical regeneration fails closed when generated inputs drift, source safety f Gate 1 validation is `pnpm run check:v34-gate1`. Gate 2 validation is `pnpm run check:v34-gate2`, with artifact freshness checked by `pnpm run check:v34-host-capability-environment-lanes` and focused package coverage in `packages/btd/__tests__/deployment-host-capability-catalog.test.ts`. +Gate 3 validation is `pnpm run check:v34-gate3`, with artifact freshness checked by `pnpm run check:v34-distributed-execution-runtime-receipts` and focused package coverage in `packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts`. The gate-quality workflow also runs spec-family, canonical-input, canon-posture drift, and diff hygiene checks. Later gates add generated artifact checks close to their deployment contract surfaces. diff --git a/BITCODE_SPEC_V34_DELTA.md b/BITCODE_SPEC_V34_DELTA.md index 83317e293..18ac95ea2 100644 --- a/BITCODE_SPEC_V34_DELTA.md +++ b/BITCODE_SPEC_V34_DELTA.md @@ -3,12 +3,12 @@ ## Status - Version: `V34` -- V34 state: Gate 2 host capability and environment lane catalog is closed over promoted V33 canon +- V34 state: Gate 3 distributed execution runtime contracts are closed over promoted V33 canon - Current canonical/latest target: `V33` - Prior canonical anchor: `BITCODE_SPEC_V33.md` - Prior generated proof appendix: `BITCODE_SPEC_V33_PROVEN.md` -- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and later deployment-depth artifacts as gates close -- Source parity state: Gate 2 closes host capability and environment lane contracts; source-side distributed execution, storage, credential, approval, repair, rehearsal, and promotion contracts remain drafted until their gates close +- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, Gate 3 artifact `.bitcode/v34-distributed-execution-runtime-receipts.json`, and later deployment-depth artifacts as gates close +- Source parity state: Gate 3 closes host capability, environment lane, and distributed execution runtime receipt contracts; source-side storage, credential, approval, repair-job registry, rehearsal, and promotion contracts remain drafted until their gates close - Spec companion: `BITCODE_SPEC_V34.md` - Notes companion: `BITCODE_SPEC_V34_NOTES.md` - Parity companion: `BITCODE_SPEC_V34_PARITY_MATRIX.md` @@ -100,6 +100,13 @@ Closure acceptance: - long-running work is not required to finish inside a request/response route handler; - receipts contain input roots, output roots, log roots, storage roots, ledger/database roots, status, and repair posture without serializing secrets or protected source. +Closure evidence: + +- `packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts` owns `DistributedExecutionRuntimeReceipt` and catalog builders for `pipeline_run`, `ptrr_agent`, `thricified_generation`, `tool_call`, `ledger_operation`, `wallet_operation`, `proof_generation`, `object_storage_write`, and `repair_job`. +- `packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts` proves root coverage, `request_response_not_required`, PTRR/ThricifiedGeneration step data, tool ids, ledger/wallet/proof/object-storage roots, terminal completion/output roots, and source-safety rejection. +- `scripts/generate-v34-distributed-execution-runtime-receipts.mjs` emits deterministic `.bitcode/v34-distributed-execution-runtime-receipts.json`. +- `scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs` and `pnpm run check:v34-gate3` fail closed on stale artifacts, missing work kinds, request/response completion assumptions, missing roots, source-safety drift, docs drift, package-script drift, and workflow drift. + ### Gate 4: Ledger Database Object Storage Deployment Posture Gate 4 defines durable storage posture. @@ -170,4 +177,4 @@ Closure acceptance: ## Completion condition -This delta is complete for Gate 2 when `version/v34` contains the Gate 2 host capability and lane contracts, source-safe generated artifacts, focused tests, workflow wiring, and `pnpm run check:v34-gate2` closure. Remaining delta closure advances through Gates 3 through 10. +This delta is complete for Gate 3 when `version/v34` contains the Gate 3 distributed execution runtime receipt contracts, source-safe generated artifact, focused tests, workflow wiring, and `pnpm run check:v34-gate3` closure. Remaining delta closure advances through Gates 4 through 10. diff --git a/BITCODE_SPEC_V34_NOTES.md b/BITCODE_SPEC_V34_NOTES.md index b3e2748b5..6ec6cf0aa 100644 --- a/BITCODE_SPEC_V34_NOTES.md +++ b/BITCODE_SPEC_V34_NOTES.md @@ -3,12 +3,12 @@ ## Status - Version: `V34` -- V34 state: Gate 2 host capability and environment lane catalog is closed over promoted V33 canon +- V34 state: Gate 3 distributed execution runtime contracts are closed over promoted V33 canon - Current canonical/latest target: `V33` - Prior canonical anchor: `BITCODE_SPEC_V33.md` - Prior generated proof appendix: `BITCODE_SPEC_V33_PROVEN.md` -- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and later deployment-depth artifacts as gates close -- Source parity state: Gate 2 closes host capability and environment lane source parity; later deployment-depth source parity remains drafted until each gate closes +- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, Gate 3 artifact `.bitcode/v34-distributed-execution-runtime-receipts.json`, and later deployment-depth artifacts as gates close +- Source parity state: Gate 3 closes host capability, environment lane, and distributed execution runtime receipt source parity; later deployment-depth source parity remains drafted until each gate closes - Scope: active draft notes for deployment depth after V33 commercial interface canon This NOTES file does not promote V34. @@ -55,7 +55,8 @@ Read the system as: - `DeploymentHostCapabilityCatalog` now makes hosts explicit: `website`, `api`, `mcp_api`, `chatgpt_app`, `pipeline_workers`, `runtime_observers`, `ledger_broadcasters`, `proof_services`, `repair_jobs`, `object_storage`, `database_projection`, and `ledger_projection`. - `EnvironmentLaneContract` now distinguishes `local`, `regtest`, `signet`, `staging-testnet`, `public-testnet`, `mainnet-ready-dry-run`, and `value-bearing-mainnet`, with `value-bearing-mainnet` visible as `blocked_future_canon_required`. - Gate 2 source truth is `packages/btd/src/deployment-host-capability-catalog.ts`; generated truth is `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`; validation is `pnpm run check:v34-gate2`. -- `DistributedExecutionRuntimeReceipt` must represent long-running Reading, settlement, wallet, proof, object-storage, and repair work without relying on route-handler duration. +- `DistributedExecutionRuntimeReceipt` now represents long-running Reading, settlement, wallet, proof, object-storage, and repair work without relying on route-handler duration. Gate 3 source truth is `packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts`; generated truth is `.bitcode/v34-distributed-execution-runtime-receipts.json`; validation is `pnpm run check:v34-gate3`. +- Receipt work kinds are `pipeline_run`, `ptrr_agent`, `thricified_generation`, `tool_call`, `ledger_operation`, `wallet_operation`, `proof_generation`, `object_storage_write`, and `repair_job`; long-running work uses `request_response_not_required` and source-safe roots instead of serialized source, prompt payloads, credentials, or wallet private material. - `DeploymentStoragePosture` must cover ledger-derived state, database projection, object storage, proof artifacts, audit logs, rollback material, retention, encryption, and repair commands. - `SecretRotationPlan` must never place secret values in tracked files or generated artifacts. - `MigrationApprovalGate` must connect schema diffs, generated types, dry-runs, reviewer approvals, and rollback plans. diff --git a/BITCODE_SPEC_V34_PARITY_MATRIX.md b/BITCODE_SPEC_V34_PARITY_MATRIX.md index 87d285733..7d61068e0 100644 --- a/BITCODE_SPEC_V34_PARITY_MATRIX.md +++ b/BITCODE_SPEC_V34_PARITY_MATRIX.md @@ -3,12 +3,12 @@ ## Status - Version: `V34` -- V34 state: Gate 2 host capability and environment lane catalog is closed over promoted V33 canon +- V34 state: Gate 3 distributed execution runtime contracts are closed over promoted V33 canon - Current canonical/latest target: `V33` - Prior canonical anchor: `BITCODE_SPEC_V33.md` - Prior generated proof appendix: `BITCODE_SPEC_V33_PROVEN.md` -- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and later deployment-depth artifacts as gates close -- Source parity state: Gate 2 closes host capability and environment lane parity; Gates 3 through 10 remain draft-required deployment-depth parity rows +- Generated structured artifact inventory: draft V34 specifying artifacts `.bitcode/v34-spec-family-report.json`, `.bitcode/v34-canonical-input-report.json`, Gate 2 artifacts `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, Gate 3 artifact `.bitcode/v34-distributed-execution-runtime-receipts.json`, and later deployment-depth artifacts as gates close +- Source parity state: Gate 3 closes host capability, environment lane, and distributed execution runtime receipt parity; Gates 4 through 10 remain draft-required deployment-depth parity rows - Spec companion: `BITCODE_SPEC_V34.md` - Notes companion: `BITCODE_SPEC_V34_NOTES.md` - Delta companion: `BITCODE_SPEC_V34_DELTA.md` @@ -55,7 +55,7 @@ No `_legacy/` source is active source truth. | Draft family and branch posture | Gate 1 | `BITCODE_SPEC_V34.md`, DELTA, NOTES, PARITY, `BITCODE_SPEC.txt`, branch `v34/gate-1-deployment-roadmap-opening` | closed | V34 family validates in draft mode over active V33 and `check:v34-gate1` passes. | | Roadmap truth | Gate 1 | `SPECIFICATIONS_ROADMAP.md`, README, PR template, workflow posture | closed | Roadmap states V33 active, V34 draft, and coherent V35-V37 responsibilities. | | Host capability and environment lane catalog | Gate 2 | `packages/btd/src/deployment-host-capability-catalog.ts`, `.bitcode/v34-deployment-host-capability-catalog.json`, `.bitcode/v34-environment-lane-contracts.json`, `packages/btd/__tests__/deployment-host-capability-catalog.test.ts`, and `check:v34-gate2` | closed | Hosts, services, lanes, storage carriers, and value-bearing blockers have package-owned rows. | -| Distributed execution runtime contracts | Gate 3 | planned runtime receipt source, tests, generated artifact, and `check:v34-gate3` | draft-required | Pipeline, tool, ledger, wallet, proof, object-storage, and repair work emits typed receipts. | +| Distributed execution runtime contracts | Gate 3 | `packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts`, `.bitcode/v34-distributed-execution-runtime-receipts.json`, `packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts`, and `check:v34-gate3` | closed | Pipeline, PTRR agent, ThricifiedGeneration, tool, ledger, wallet, proof, object-storage, and repair work emits typed receipts. | | Ledger/database/object-storage posture | Gate 4 | planned storage posture source, tests, generated artifact, and `check:v34-gate4` | draft-required | Ledger-derived state, database projection, object storage, proof artifacts, audit logs, backups, and rollback material are durable and repairable. | | Secret rotation and credential boundaries | Gate 5 | planned secret-family source, tests, generated artifact, and `check:v34-gate5` | draft-required | Secret values stay out of tracked files and logs while rotation, leak response, and runtime availability are provable. | | Migration CI/CD deployment approval gates | Gate 6 | planned approval gate source, workflows, generated artifact, and `check:v34-gate6` | draft-required | Schema migration, generated types, route scans, builds, deployment approvals, and promotion commits fail closed. | @@ -79,6 +79,8 @@ No `_legacy/` source is active source truth. | Host/lane catalog package source | `packages/btd/src/deployment-host-capability-catalog.ts` owns `DeploymentHostCapabilityCatalog` and `EnvironmentLaneContract` builders | closed | | Gate 2 generated artifacts | `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json` are deterministic and source-safe | closed | | Value-bearing mainnet blocker | `value-bearing-mainnet` remains `blocked_future_canon_required` and admits no hosts | closed | +| Gate 3 generated artifact | `.bitcode/v34-distributed-execution-runtime-receipts.json` is deterministic and source-safe | closed | +| Runtime route boundary | Long-running `DistributedExecutionRuntimeReceipt` rows use `request_response_not_required` instead of request/response completion | closed | ## Gate 1 Parity @@ -107,9 +109,12 @@ No `_legacy/` source is active source truth. | Requirement | Source evidence | Current V34 judgment | | --- | --- | --- | -| Distributed execution runtime receipt exists | planned package-owned type and builders | draft-required | -| Long-running route boundary is respected | planned route/worker tests | draft-required | -| Pipeline, tool, ledger, wallet, proof, storage, and repair receipt roots are covered | planned generated artifact | draft-required | +| Distributed execution runtime receipt exists | `packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts`, `packages/pipeline-hosts/src/index.ts`, and `.bitcode/v34-distributed-execution-runtime-receipts.json` | closed | +| Long-running route boundary is respected | `request_response_not_required` fixtures, focused tests, generated artifact coverage, and `check:v34-gate3` | closed | +| Pipeline, tool, ledger, wallet, proof, storage, and repair receipt roots are covered | `.bitcode/v34-distributed-execution-runtime-receipts.json` covers input roots, output roots, log roots, object-storage roots, ledger/database roots, wallet roots, proof roots, and repair posture | closed | +| PTRR and ThricifiedGeneration receipt precision | `ptrr_agent` and `thricified_generation` receipt rows include PTRR step and ThricifiedGeneration step data without protected prompt or source payloads | closed | +| Storage and repair receipt precision | `object_storage_write` and `repair_job` receipt rows carry source-safe roots, replay commands, and repair posture without serializing protected source | closed | +| Source-safety boundary | Gate 3 tests and checker reject secret-shaped text and protected source markers in receipt fields and generated artifact output | closed | ## Gate 4 Parity diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md index 5dece8f1b..d94e3dfbd 100644 --- a/SPECIFICATIONS_ROADMAP.md +++ b/SPECIFICATIONS_ROADMAP.md @@ -5,10 +5,11 @@ - Current active canonical pointer: `BITCODE_SPEC.txt` -> `V33` - Current active canon: `BITCODE_SPEC_V33.md` - Current draft target: `BITCODE_SPEC_V34.md` -- Current working gate: V34 Gate 3 Distributed Execution Runtime Contracts, following closed Gate 2 host capability and environment lane catalog work. +- Current working gate: V34 Gate 4 Ledger Database Object Storage Deployment Posture, following closed Gate 3 distributed execution runtime contract work. - Latest closed version: V33 Commercial Interface Depth, which promoted MCP API, ChatGPT App, public API, package-owned schemas, interface authorization, Read license and AssetPack rights contracts, compatibility matrices, telemetry/proof hooks, consumer UX proof, and V33 promotion readiness. - Recent V33 closure anchor: V33 Gate 10 Promotion Readiness generated V33 proof support, promoted `BITCODE_SPEC.txt` to `V33`, and prepared V33 active / V34 draft runtime posture. - V34 Gate 2 closure anchor: deployment-depth now owns package-backed `DeploymentHostCapabilityCatalog` and `EnvironmentLaneContract` source, deterministic `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and visible `value-bearing-mainnet` blocking through `blocked_future_canon_required`. +- V34 Gate 3 closure anchor: deployment-depth now owns package-backed `DistributedExecutionRuntimeReceipt` source, deterministic `.bitcode/v34-distributed-execution-runtime-receipts.json`, `request_response_not_required` long-running work posture, and source-safe roots for pipeline, PTRR agent, ThricifiedGeneration, tool, ledger, wallet, proof, object-storage, and repair work. - Purpose: concise running index of Bitcode/ENGI specification history, current work, and planned work. This roadmap is not an active system specification. diff --git a/package.json b/package.json index 823f3d837..faab1f90b 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,9 @@ "generate:v34-host-capability-environment-lanes": "node scripts/generate-v34-host-capability-environment-lanes.mjs", "check:v34-host-capability-environment-lanes": "node scripts/generate-v34-host-capability-environment-lanes.mjs --check", "check:v34-gate2": "node scripts/check-v34-gate2-host-capability-environment-lanes.mjs", + "generate:v34-distributed-execution-runtime-receipts": "node scripts/generate-v34-distributed-execution-runtime-receipts.mjs", + "check:v34-distributed-execution-runtime-receipts": "node scripts/generate-v34-distributed-execution-runtime-receipts.mjs --check", + "check:v34-gate3": "node scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs", "check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic", "check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title", "check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24", diff --git a/packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts b/packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts new file mode 100644 index 000000000..fb51f0977 --- /dev/null +++ b/packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts @@ -0,0 +1,202 @@ +import { + DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS, + buildDistributedExecutionRuntimeReceipt, + buildDistributedExecutionRuntimeReceiptCatalog, + buildDistributedExecutionRuntimeReceiptFixtures, +} from '../distributed-execution-runtime-receipt'; + +const OPENAI_SECRET_PREFIX = `${['sk', 'proj'].join('-')}-`; + +describe('distributed execution runtime receipts', () => { + it('catalogs pipeline runs, PTRR agents, ThricifiedGenerations, tool calls, ledger operations, wallet operations, proof generation, object-storage writes, and repair jobs', () => { + const catalog = buildDistributedExecutionRuntimeReceiptCatalog(); + + expect(catalog.kind).toBe('bitcode.distributed_execution_runtime_receipt_catalog'); + expect(catalog.schemaId).toBe('bitcode.distributedExecutionRuntimeReceiptCatalog.v1'); + expect(catalog.requiredWorkKinds).toEqual([...DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS]); + expect(catalog.observedWorkKinds).toEqual([...DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS].sort()); + expect(catalog.missingWorkKinds).toEqual([]); + expect(catalog.receiptCount).toBe(DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS.length); + expect(catalog.requestResponseCompletionRequired).toBe(false); + expect(catalog.credentialsSerialized).toBe(false); + expect(catalog.protectedSourceVisible).toBe(false); + expect(catalog.sourceSafety.sourceSafe).toBe(true); + }); + + it('keeps long-running runtime work detached from request/response route handler completion', () => { + const catalog = buildDistributedExecutionRuntimeReceiptCatalog(); + + expect(catalog.receipts.every((receipt) => receipt.routeHandlerBoundary)).toBe(true); + expect( + catalog.receipts.every( + (receipt) => receipt.routeHandlerBoundary === 'request_response_not_required', + ), + ).toBe(true); + }); + + it('covers required roots for pipeline, tool, ledger, wallet, proof, storage, and repair receipts', () => { + const catalog = buildDistributedExecutionRuntimeReceiptCatalog(); + const byKind = Object.fromEntries( + catalog.receipts.map((receipt) => [receipt.workKind, receipt]), + ); + + for (const receipt of catalog.receipts) { + expect(receipt.inputRoot).toMatch(/^sha256:/); + expect(receipt.outputRoot).toMatch(/^sha256:/); + expect(receipt.logRoot).toMatch(/^sha256:/); + expect(receipt.databaseProjectionRoot).toMatch(/^sha256:/); + expect(receipt.repairPosture).toBeTruthy(); + expect(receipt.receiptRoot).toMatch(/^distributed-execution-runtime-receipt:/); + expect(JSON.stringify(receipt)).not.toContain(OPENAI_SECRET_PREFIX); + expect(JSON.stringify(receipt)).not.toContain('raw source'); + } + + expect(byKind.pipeline_run.objectStorageRoot).toMatch(/^sha256:/); + expect(byKind.pipeline_run.ledgerProjectionRoot).toMatch(/^sha256:/); + expect(byKind.pipeline_run.proofRoot).toMatch(/^sha256:/); + expect(byKind.ptrr_agent.agentId).toBe('ReadFitsFindingSynthesisDiscoveryAgent'); + expect(byKind.ptrr_agent.ptrrStep).toBe('plan'); + expect(byKind.thricified_generation.agentId).toBe( + 'ReadFitsFindingSynthesisDiscoveryAgent', + ); + expect(byKind.thricified_generation.ptrrStep).toBe('plan'); + expect(byKind.thricified_generation.thricifiedGenerationStep).toBe('reason'); + expect(byKind.tool_call.toolId).toBe('AssetPackLexicalDepositorySearchTool'); + expect(byKind.ledger_operation.ledgerProjectionRoot).toMatch(/^sha256:/); + expect(byKind.wallet_operation.walletOperationRoot).toMatch(/^sha256:/); + expect(byKind.proof_generation.proofRoot).toMatch(/^sha256:/); + expect(byKind.object_storage_write.objectStorageRoot).toMatch(/^sha256:/); + expect(byKind.repair_job.status).toBe('repaired'); + expect(byKind.repair_job.ledgerProjectionRoot).toMatch(/^sha256:/); + }); + + it('allows only short local blocking route handler work', () => { + const [fixture] = buildDistributedExecutionRuntimeReceiptFixtures(); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...fixture, + laneId: 'local', + workKind: 'tool_call', + routeHandlerBoundary: 'blocking_allowed_for_short_local_work', + toolId: 'LocalSmokeTool', + }), + ).not.toThrow(); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...fixture, + routeHandlerBoundary: 'blocking_allowed_for_short_local_work', + }), + ).toThrow(/only allowed for short local work/); + }); + + it('fails closed when a work kind is missing from the catalog', () => { + const receipts = buildDistributedExecutionRuntimeReceiptFixtures().filter( + (receipt) => receipt.workKind !== 'wallet_operation', + ); + + expect(() => buildDistributedExecutionRuntimeReceiptCatalog({ receipts })).toThrow( + /missing work kinds: wallet_operation/, + ); + }); + + it('fails closed when successful runtime receipts omit output roots', () => { + const [fixture] = buildDistributedExecutionRuntimeReceiptFixtures(); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...fixture, + outputRoot: undefined, + }), + ).toThrow(/require outputRoot/); + }); + + it('fails closed when terminal runtime receipts omit completedAt', () => { + const [fixture] = buildDistributedExecutionRuntimeReceiptFixtures(); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...fixture, + completedAt: undefined, + }), + ).toThrow(/require completedAt/); + }); + + it('fails closed when PTRR and ThricifiedGeneration receipts omit formal step data', () => { + const ptrrAgent = buildDistributedExecutionRuntimeReceiptFixtures().find( + (receipt) => receipt.workKind === 'ptrr_agent', + ); + const generation = buildDistributedExecutionRuntimeReceiptFixtures().find( + (receipt) => receipt.workKind === 'thricified_generation', + ); + + expect(ptrrAgent).toBeTruthy(); + expect(generation).toBeTruthy(); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...ptrrAgent!, + agentId: undefined, + }), + ).toThrow(/PTRR agent receipts require agentId/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...generation!, + thricifiedGenerationStep: undefined, + }), + ).toThrow(/ThricifiedGeneration receipts require/); + }); + + it('fails closed when tool, ledger, wallet, proof, storage, and repair receipts omit their owned roots', () => { + const fixtures = buildDistributedExecutionRuntimeReceiptFixtures(); + const byKind = Object.fromEntries(fixtures.map((receipt) => [receipt.workKind, receipt])); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.tool_call, + toolId: undefined, + }), + ).toThrow(/Tool call receipts require toolId/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.ledger_operation, + ledgerProjectionRoot: undefined, + }), + ).toThrow(/Ledger operation receipts require ledgerProjectionRoot/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.wallet_operation, + walletOperationRoot: undefined, + }), + ).toThrow(/Wallet operation receipts require walletOperationRoot/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.proof_generation, + proofRoot: undefined, + }), + ).toThrow(/Proof generation receipts require proofRoot/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.object_storage_write, + objectStorageRoot: undefined, + }), + ).toThrow(/Object storage write receipts require objectStorageRoot/); + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...byKind.repair_job, + outputRoot: undefined, + }), + ).toThrow(/require outputRoot/); + }); + + it('fails closed on secret-shaped or protected-source receipt text', () => { + const [fixture] = buildDistributedExecutionRuntimeReceiptFixtures(); + + expect(() => + buildDistributedExecutionRuntimeReceipt({ + ...fixture, + repairPosture: `${OPENAI_SECRET_PREFIX}abcdefghijklmnop1234567890`, + }), + ).toThrow(/must not contain secrets or non-disclosable source/); + }); +}); diff --git a/packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts b/packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts new file mode 100644 index 000000000..5f6c3cc3d --- /dev/null +++ b/packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts @@ -0,0 +1,620 @@ +import { createHash } from 'node:crypto'; + +export const DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS = [ + 'pipeline_run', + 'ptrr_agent', + 'thricified_generation', + 'tool_call', + 'ledger_operation', + 'wallet_operation', + 'proof_generation', + 'object_storage_write', + 'repair_job', +] as const; + +export type DistributedExecutionRuntimeWorkKind = + (typeof DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS)[number]; + +export const DISTRIBUTED_EXECUTION_RUNTIME_HOST_IDS = [ + 'website', + 'api', + 'mcp_api', + 'chatgpt_app', + 'pipeline_workers', + 'runtime_observers', + 'ledger_broadcasters', + 'proof_services', + 'repair_jobs', + 'object_storage', + 'database_projection', + 'ledger_projection', +] as const; + +export type DistributedExecutionRuntimeHostId = + (typeof DISTRIBUTED_EXECUTION_RUNTIME_HOST_IDS)[number]; + +export const DISTRIBUTED_EXECUTION_RUNTIME_LANE_IDS = [ + 'local', + 'regtest', + 'signet', + 'staging-testnet', + 'public-testnet', + 'mainnet-ready-dry-run', +] as const; + +export type DistributedExecutionRuntimeLaneId = + (typeof DISTRIBUTED_EXECUTION_RUNTIME_LANE_IDS)[number]; + +export type DistributedExecutionRuntimeStatus = + | 'queued' + | 'running' + | 'succeeded' + | 'failed' + | 'blocked' + | 'repaired'; + +export type DistributedExecutionRuntimeRouteBoundary = + | 'request_response_not_required' + | 'blocking_allowed_for_short_local_work'; + +export type DistributedExecutionRuntimePtrrStep = 'plan' | 'try' | 'refine' | 'retry'; + +export type DistributedExecutionRuntimeThricifiedGenerationStep = + | 'reason' + | 'judge' + | 'structured_output'; + +export interface DistributedExecutionRuntimeReceiptInput { + receiptId?: string; + executionId: string; + hostId: DistributedExecutionRuntimeHostId; + laneId: DistributedExecutionRuntimeLaneId; + workKind: DistributedExecutionRuntimeWorkKind; + commandOrPipelineId: string; + status: DistributedExecutionRuntimeStatus; + routeHandlerBoundary: DistributedExecutionRuntimeRouteBoundary; + startedAt: string; + completedAt?: string; + inputRoot: string; + outputRoot?: string; + logRoot: string; + objectStorageRoot?: string; + ledgerProjectionRoot?: string; + databaseProjectionRoot?: string; + walletOperationRoot?: string; + proofRoot?: string; + parentReceiptRoot?: string; + phaseId?: string; + agentId?: string; + ptrrStep?: DistributedExecutionRuntimePtrrStep; + thricifiedGenerationStep?: DistributedExecutionRuntimeThricifiedGenerationStep; + toolId?: string; + repairPosture: string; + replayCommand: string; +} + +export interface DistributedExecutionRuntimeReceipt { + kind: 'bitcode.distributed_execution_runtime_receipt'; + schemaId: 'bitcode.distributedExecutionRuntimeReceipt.v1'; + receiptId: string; + executionId: string; + hostId: DistributedExecutionRuntimeHostId; + laneId: DistributedExecutionRuntimeLaneId; + workKind: DistributedExecutionRuntimeWorkKind; + commandOrPipelineId: string; + status: DistributedExecutionRuntimeStatus; + routeHandlerBoundary: DistributedExecutionRuntimeRouteBoundary; + startedAt: string; + completedAt?: string; + inputRoot: string; + outputRoot?: string; + logRoot: string; + objectStorageRoot?: string; + ledgerProjectionRoot?: string; + databaseProjectionRoot?: string; + walletOperationRoot?: string; + proofRoot?: string; + parentReceiptRoot?: string; + phaseId?: string; + agentId?: string; + ptrrStep?: DistributedExecutionRuntimePtrrStep; + thricifiedGenerationStep?: DistributedExecutionRuntimeThricifiedGenerationStep; + toolId?: string; + repairPosture: string; + replayCommand: string; + protectedSourceVisible: false; + credentialsSerialized: false; + sourceSafety: DistributedExecutionRuntimeSourceSafety; + receiptRoot: string; +} + +export interface DistributedExecutionRuntimeSourceSafety { + sourceSafe: true; + protectedSourceVisible: false; + containsProtectedSource: false; + containsSecret: false; + credentialsSerialized: false; +} + +export interface DistributedExecutionRuntimeReceiptCatalogInput { + receipts?: readonly DistributedExecutionRuntimeReceiptInput[]; + requiredWorkKinds?: readonly DistributedExecutionRuntimeWorkKind[]; +} + +export interface DistributedExecutionRuntimeReceiptCatalog { + kind: 'bitcode.distributed_execution_runtime_receipt_catalog'; + schemaId: 'bitcode.distributedExecutionRuntimeReceiptCatalog.v1'; + catalogRoot: string; + receiptCount: number; + requiredWorkKinds: DistributedExecutionRuntimeWorkKind[]; + observedWorkKinds: DistributedExecutionRuntimeWorkKind[]; + missingWorkKinds: DistributedExecutionRuntimeWorkKind[]; + receipts: DistributedExecutionRuntimeReceipt[]; + requestResponseCompletionRequired: false; + protectedSourceVisible: false; + credentialsSerialized: false; + sourceSafety: DistributedExecutionRuntimeSourceSafety; +} + +const SECRET_OR_SOURCE_PATTERNS = [ + new RegExp(`${['sb', 'secret'].join('_')}__`, 'iu'), + /\bsk-(?:proj|live|test)?[-_A-Za-z0-9]{16,}\b/u, + /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/u, + /-----BEGIN [A-Z ]*PRIVATE KEY-----/u, + /\bprivate\s+key\b/iu, + /\bwallet\s+seed\b/iu, + /\bmnemonic\b/iu, + /\braw\s+source\b/iu, +]; + +const ROOT_PATTERN = /^(?:sha256|receipt|root):[a-z0-9._:-]{8,}$/iu; + +const SOURCE_SAFETY: DistributedExecutionRuntimeSourceSafety = { + sourceSafe: true, + protectedSourceVisible: false, + containsProtectedSource: false, + containsSecret: false, + credentialsSerialized: false, +}; + +export function buildDistributedExecutionRuntimeReceiptFixtures(): DistributedExecutionRuntimeReceiptInput[] { + const base = { + laneId: 'staging-testnet' as const, + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + routeHandlerBoundary: 'request_response_not_required' as const, + status: 'succeeded' as const, + databaseProjectionRoot: 'sha256:database-projection-root', + logRoot: 'sha256:runtime-log-root', + replayCommand: 'pnpm run check:v34-gate3', + }; + + return [ + { + ...base, + executionId: 'execution-read-fits-finding-synthesis', + hostId: 'pipeline_workers', + workKind: 'pipeline_run', + commandOrPipelineId: 'ReadFitsFindingSynthesis', + phaseId: 'discovery', + inputRoot: 'sha256:pipeline-input-root', + outputRoot: 'sha256:pipeline-output-root', + objectStorageRoot: 'sha256:pipeline-object-storage-root', + ledgerProjectionRoot: 'sha256:pipeline-ledger-projection-root', + proofRoot: 'sha256:pipeline-proof-root', + repairPosture: 'retry-detached-pipeline-from-input-root', + }, + { + ...base, + executionId: 'execution-read-fits-agent', + hostId: 'pipeline_workers', + workKind: 'ptrr_agent', + commandOrPipelineId: 'ReadFitsFindingSynthesisDiscoveryAgent', + parentReceiptRoot: 'receipt:pipeline-run-root', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'plan', + inputRoot: 'sha256:agent-input-root', + outputRoot: 'sha256:agent-output-root', + proofRoot: 'sha256:agent-proof-root', + repairPosture: 'resume-ptrr-agent-from-step-root', + }, + { + ...base, + executionId: 'execution-thricified-generation', + hostId: 'pipeline_workers', + workKind: 'thricified_generation', + commandOrPipelineId: 'ReadFitsFindingSynthesisDiscoveryAgent.plan.reason', + parentReceiptRoot: 'receipt:ptrr-agent-root', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'plan', + thricifiedGenerationStep: 'reason', + inputRoot: 'sha256:generation-input-root', + outputRoot: 'sha256:generation-output-root', + proofRoot: 'sha256:generation-proof-root', + repairPosture: 'regenerate-from-redacted-prompt-and-context-root', + }, + { + ...base, + executionId: 'execution-depository-search-tool', + hostId: 'pipeline_workers', + workKind: 'tool_call', + commandOrPipelineId: 'AssetPackLexicalDepositorySearchTool', + parentReceiptRoot: 'receipt:thricified-generation-root', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'try', + toolId: 'AssetPackLexicalDepositorySearchTool', + inputRoot: 'sha256:tool-input-root', + outputRoot: 'sha256:tool-output-root', + proofRoot: 'sha256:tool-proof-root', + repairPosture: 'rerun-tool-from-input-root-with-source-safe-query', + }, + { + ...base, + executionId: 'execution-ledger-operation', + hostId: 'ledger_projection', + workKind: 'ledger_operation', + commandOrPipelineId: 'ledger.project.read-rights', + inputRoot: 'sha256:ledger-input-root', + outputRoot: 'sha256:ledger-output-root', + ledgerProjectionRoot: 'sha256:ledger-projection-root', + proofRoot: 'sha256:ledger-proof-root', + repairPosture: 'hold-unlock-and-replay-ledger-projection', + }, + { + ...base, + executionId: 'execution-wallet-operation', + hostId: 'ledger_broadcasters', + laneId: 'signet', + workKind: 'wallet_operation', + commandOrPipelineId: 'btc.fee.sign-and-broadcast', + inputRoot: 'sha256:wallet-input-root', + outputRoot: 'sha256:wallet-output-root', + walletOperationRoot: 'sha256:wallet-operation-root', + proofRoot: 'sha256:wallet-proof-root', + repairPosture: 'deny-broadcast-until-wallet-policy-repaired', + }, + { + ...base, + executionId: 'execution-proof-generation', + hostId: 'proof_services', + workKind: 'proof_generation', + commandOrPipelineId: 'v34.deployment.proof.generate', + inputRoot: 'sha256:proof-input-root', + outputRoot: 'sha256:proof-output-root', + proofRoot: 'sha256:proof-generation-root', + repairPosture: 'regenerate-proof-from-canonical-inputs', + }, + { + ...base, + executionId: 'execution-object-storage-write', + hostId: 'object_storage', + workKind: 'object_storage_write', + commandOrPipelineId: 'assetpack.preview.persist', + inputRoot: 'sha256:object-storage-input-root', + outputRoot: 'sha256:object-storage-output-root', + objectStorageRoot: 'sha256:object-storage-root', + proofRoot: 'sha256:object-storage-proof-root', + repairPosture: 'lock-delivery-and-rewrite-from-authorized-artifact-root', + }, + { + ...base, + executionId: 'execution-repair-job', + hostId: 'repair_jobs', + workKind: 'repair_job', + commandOrPipelineId: 'projection.repair', + status: 'repaired', + inputRoot: 'sha256:repair-input-root', + outputRoot: 'sha256:repair-output-root', + objectStorageRoot: 'sha256:repair-object-storage-root', + ledgerProjectionRoot: 'sha256:repair-ledger-projection-root', + proofRoot: 'sha256:repair-proof-root', + repairPosture: 'repair-complete-with-replayable-proof-root', + }, + ]; +} + +export function buildDistributedExecutionRuntimeReceipt( + input: DistributedExecutionRuntimeReceiptInput, +): DistributedExecutionRuntimeReceipt { + const workKind = assertWorkKind(input.workKind); + const hostId = assertHostId(input.hostId); + const laneId = assertLaneId(input.laneId); + const status = assertStatus(input.status); + const routeHandlerBoundary = assertRouteBoundary(input.routeHandlerBoundary); + const receiptId = + input.receiptId ?? + stableRoot('distributed-execution-runtime-receipt-id', [ + input.executionId, + hostId, + laneId, + workKind, + input.commandOrPipelineId, + input.inputRoot, + ]); + + const receipt = { + kind: 'bitcode.distributed_execution_runtime_receipt' as const, + schemaId: 'bitcode.distributedExecutionRuntimeReceipt.v1' as const, + receiptId: assertSourceSafeString(receiptId, 'receiptId'), + executionId: assertSourceSafeString(input.executionId, 'executionId'), + hostId, + laneId, + workKind, + commandOrPipelineId: assertSourceSafeString(input.commandOrPipelineId, 'commandOrPipelineId'), + status, + routeHandlerBoundary, + startedAt: assertSourceSafeString(input.startedAt, 'startedAt'), + completedAt: input.completedAt + ? assertSourceSafeString(input.completedAt, 'completedAt') + : undefined, + inputRoot: assertRoot(input.inputRoot, 'inputRoot'), + outputRoot: input.outputRoot ? assertRoot(input.outputRoot, 'outputRoot') : undefined, + logRoot: assertRoot(input.logRoot, 'logRoot'), + objectStorageRoot: input.objectStorageRoot + ? assertRoot(input.objectStorageRoot, 'objectStorageRoot') + : undefined, + ledgerProjectionRoot: input.ledgerProjectionRoot + ? assertRoot(input.ledgerProjectionRoot, 'ledgerProjectionRoot') + : undefined, + databaseProjectionRoot: input.databaseProjectionRoot + ? assertRoot(input.databaseProjectionRoot, 'databaseProjectionRoot') + : undefined, + walletOperationRoot: input.walletOperationRoot + ? assertRoot(input.walletOperationRoot, 'walletOperationRoot') + : undefined, + proofRoot: input.proofRoot ? assertRoot(input.proofRoot, 'proofRoot') : undefined, + parentReceiptRoot: input.parentReceiptRoot + ? assertRoot(input.parentReceiptRoot, 'parentReceiptRoot') + : undefined, + phaseId: input.phaseId ? assertSourceSafeString(input.phaseId, 'phaseId') : undefined, + agentId: input.agentId ? assertSourceSafeString(input.agentId, 'agentId') : undefined, + ptrrStep: input.ptrrStep ? assertPtrrStep(input.ptrrStep) : undefined, + thricifiedGenerationStep: input.thricifiedGenerationStep + ? assertThricifiedGenerationStep(input.thricifiedGenerationStep) + : undefined, + toolId: input.toolId ? assertSourceSafeString(input.toolId, 'toolId') : undefined, + repairPosture: assertSourceSafeString(input.repairPosture, 'repairPosture'), + replayCommand: assertSourceSafeString(input.replayCommand, 'replayCommand'), + protectedSourceVisible: false as const, + credentialsSerialized: false as const, + sourceSafety: SOURCE_SAFETY, + }; + + assertReceiptInvariants(receipt); + + return { + ...receipt, + receiptRoot: stableRoot('distributed-execution-runtime-receipt', [ + receipt.receiptId, + receipt.executionId, + receipt.hostId, + receipt.laneId, + receipt.workKind, + receipt.commandOrPipelineId, + receipt.status, + receipt.routeHandlerBoundary, + receipt.inputRoot, + receipt.outputRoot ?? 'pending-output', + receipt.logRoot, + receipt.objectStorageRoot ?? 'no-object-storage-root', + receipt.ledgerProjectionRoot ?? 'no-ledger-root', + receipt.databaseProjectionRoot ?? 'no-database-root', + receipt.walletOperationRoot ?? 'no-wallet-root', + receipt.proofRoot ?? 'no-proof-root', + receipt.parentReceiptRoot ?? 'root-receipt', + receipt.phaseId ?? 'no-phase', + receipt.agentId ?? 'no-agent', + receipt.ptrrStep ?? 'no-ptrr-step', + receipt.thricifiedGenerationStep ?? 'no-thricified-generation-step', + receipt.toolId ?? 'no-tool', + receipt.repairPosture, + receipt.replayCommand, + ]), + }; +} + +export function buildDistributedExecutionRuntimeReceiptCatalog( + input: DistributedExecutionRuntimeReceiptCatalogInput = {}, +): DistributedExecutionRuntimeReceiptCatalog { + const receipts = (input.receipts ?? buildDistributedExecutionRuntimeReceiptFixtures()).map( + buildDistributedExecutionRuntimeReceipt, + ); + const requiredWorkKinds = [ + ...(input.requiredWorkKinds ?? DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS), + ]; + const observedWorkKinds = Array.from(new Set(receipts.map((receipt) => receipt.workKind))).sort(); + const missingWorkKinds = requiredWorkKinds.filter( + (workKind) => !observedWorkKinds.includes(workKind), + ); + const duplicateReceiptIds = findDuplicates(receipts.map((receipt) => receipt.receiptId)); + + if (missingWorkKinds.length) { + throw new Error(`Distributed execution runtime receipts missing work kinds: ${missingWorkKinds.join(', ')}.`); + } + if (duplicateReceiptIds.length) { + throw new Error(`Distributed execution runtime receipts contain duplicate receipt ids: ${duplicateReceiptIds.join(', ')}.`); + } + + return { + kind: 'bitcode.distributed_execution_runtime_receipt_catalog', + schemaId: 'bitcode.distributedExecutionRuntimeReceiptCatalog.v1', + catalogRoot: stableRoot('distributed-execution-runtime-receipt-catalog', [ + ...receipts.map((receipt) => receipt.receiptRoot), + requiredWorkKinds.join(','), + ]), + receiptCount: receipts.length, + requiredWorkKinds, + observedWorkKinds, + missingWorkKinds, + receipts, + requestResponseCompletionRequired: false, + protectedSourceVisible: false, + credentialsSerialized: false, + sourceSafety: SOURCE_SAFETY, + }; +} + +function assertReceiptInvariants( + receipt: Omit, +): void { + if ( + receipt.routeHandlerBoundary === 'blocking_allowed_for_short_local_work' && + receipt.laneId !== 'local' + ) { + throw new Error('Blocking route handler completion is only allowed for short local work.'); + } + if (receipt.routeHandlerBoundary !== 'request_response_not_required') { + if (receipt.workKind !== 'tool_call' && receipt.status === 'running') { + throw new Error('Long-running distributed work must not require request/response completion.'); + } + } + if (['succeeded', 'failed', 'blocked', 'repaired'].includes(receipt.status)) { + if (!receipt.completedAt) { + throw new Error('Terminal distributed execution receipts require completedAt.'); + } + } + if (['succeeded', 'repaired'].includes(receipt.status) && !receipt.outputRoot) { + throw new Error('Successful or repaired distributed execution receipts require outputRoot.'); + } + if (receipt.workKind === 'ptrr_agent' && !receipt.agentId) { + throw new Error('PTRR agent receipts require agentId.'); + } + if (receipt.workKind === 'thricified_generation') { + if (!receipt.agentId || !receipt.ptrrStep || !receipt.thricifiedGenerationStep) { + throw new Error('ThricifiedGeneration receipts require agentId, PTRR step, and generation step.'); + } + } + if (receipt.workKind === 'tool_call' && !receipt.toolId) { + throw new Error('Tool call receipts require toolId.'); + } + if (receipt.workKind === 'ledger_operation' && !receipt.ledgerProjectionRoot) { + throw new Error('Ledger operation receipts require ledgerProjectionRoot.'); + } + if (receipt.workKind === 'wallet_operation' && !receipt.walletOperationRoot) { + throw new Error('Wallet operation receipts require walletOperationRoot.'); + } + if (receipt.workKind === 'proof_generation' && !receipt.proofRoot) { + throw new Error('Proof generation receipts require proofRoot.'); + } + if (receipt.workKind === 'object_storage_write' && !receipt.objectStorageRoot) { + throw new Error('Object storage write receipts require objectStorageRoot.'); + } + if (receipt.workKind === 'repair_job' && !receipt.outputRoot) { + throw new Error('Repair job receipts require outputRoot.'); + } +} + +function assertWorkKind(workKind: string): DistributedExecutionRuntimeWorkKind { + if (!DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS.includes(workKind as DistributedExecutionRuntimeWorkKind)) { + throw new Error(`Unsupported distributed execution runtime work kind: ${workKind}.`); + } + + return workKind as DistributedExecutionRuntimeWorkKind; +} + +function assertHostId(hostId: string): DistributedExecutionRuntimeHostId { + if (!DISTRIBUTED_EXECUTION_RUNTIME_HOST_IDS.includes(hostId as DistributedExecutionRuntimeHostId)) { + throw new Error(`Unsupported distributed execution runtime host id: ${hostId}.`); + } + + return hostId as DistributedExecutionRuntimeHostId; +} + +function assertLaneId(laneId: string): DistributedExecutionRuntimeLaneId { + if (!DISTRIBUTED_EXECUTION_RUNTIME_LANE_IDS.includes(laneId as DistributedExecutionRuntimeLaneId)) { + throw new Error(`Unsupported distributed execution runtime lane id: ${laneId}.`); + } + + return laneId as DistributedExecutionRuntimeLaneId; +} + +function assertStatus(status: string): DistributedExecutionRuntimeStatus { + const allowed: readonly DistributedExecutionRuntimeStatus[] = [ + 'queued', + 'running', + 'succeeded', + 'failed', + 'blocked', + 'repaired', + ]; + if (!allowed.includes(status as DistributedExecutionRuntimeStatus)) { + throw new Error(`Unsupported distributed execution runtime status: ${status}.`); + } + + return status as DistributedExecutionRuntimeStatus; +} + +function assertRouteBoundary(boundary: string): DistributedExecutionRuntimeRouteBoundary { + const allowed: readonly DistributedExecutionRuntimeRouteBoundary[] = [ + 'request_response_not_required', + 'blocking_allowed_for_short_local_work', + ]; + if (!allowed.includes(boundary as DistributedExecutionRuntimeRouteBoundary)) { + throw new Error(`Unsupported distributed execution route boundary: ${boundary}.`); + } + + return boundary as DistributedExecutionRuntimeRouteBoundary; +} + +function assertPtrrStep(step: string): DistributedExecutionRuntimePtrrStep { + const allowed: readonly DistributedExecutionRuntimePtrrStep[] = ['plan', 'try', 'refine', 'retry']; + if (!allowed.includes(step as DistributedExecutionRuntimePtrrStep)) { + throw new Error(`Unsupported PTRR step: ${step}.`); + } + + return step as DistributedExecutionRuntimePtrrStep; +} + +function assertThricifiedGenerationStep( + step: string, +): DistributedExecutionRuntimeThricifiedGenerationStep { + const allowed: readonly DistributedExecutionRuntimeThricifiedGenerationStep[] = [ + 'reason', + 'judge', + 'structured_output', + ]; + if (!allowed.includes(step as DistributedExecutionRuntimeThricifiedGenerationStep)) { + throw new Error(`Unsupported ThricifiedGeneration step: ${step}.`); + } + + return step as DistributedExecutionRuntimeThricifiedGenerationStep; +} + +function assertRoot(root: string, label: string): string { + const text = assertSourceSafeString(root, label); + if (!ROOT_PATTERN.test(text)) { + throw new Error(`${label} must be a source-safe root.`); + } + + return text; +} + +function assertSourceSafeString(value: unknown, label: string): string { + if (typeof value !== 'string' || value.trim().length === 0) { + throw new Error(`${label} must be a non-empty string.`); + } + if (SECRET_OR_SOURCE_PATTERNS.some((pattern) => pattern.test(value))) { + throw new Error(`${label} must not contain secrets or non-disclosable source.`); + } + + return value; +} + +function findDuplicates(values: readonly string[]): string[] { + const seen = new Set(); + const duplicate = new Set(); + for (const value of values) { + if (seen.has(value)) duplicate.add(value); + seen.add(value); + } + + return [...duplicate].sort(); +} + +function stableRoot(prefix: string, parts: string[]): string { + const hash = createHash('sha256').update(parts.join('\u001f')).digest('hex').slice(0, 24); + return `${prefix}:${hash}`; +} diff --git a/packages/pipeline-hosts/src/index.ts b/packages/pipeline-hosts/src/index.ts index 44d80e47e..711ce5dc3 100644 --- a/packages/pipeline-hosts/src/index.ts +++ b/packages/pipeline-hosts/src/index.ts @@ -1,4 +1,5 @@ export * from './asset-pack-harness'; +export * from './distributed-execution-runtime-receipt'; export * from './manifest'; export * from './types'; export * from './vercel-sandbox-host'; diff --git a/packages/protocol/src/canonical/v21-specifying.js b/packages/protocol/src/canonical/v21-specifying.js index 728b2e8f9..386839c0a 100644 --- a/packages/protocol/src/canonical/v21-specifying.js +++ b/packages/protocol/src/canonical/v21-specifying.js @@ -375,7 +375,8 @@ function buildV21LikeProfile(version) { ...(version === 'V34' ? [ '.bitcode/v34-deployment-host-capability-catalog.json', - '.bitcode/v34-environment-lane-contracts.json' + '.bitcode/v34-environment-lane-contracts.json', + '.bitcode/v34-distributed-execution-runtime-receipts.json' ] : []), ...(version === 'V26' diff --git a/scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs b/scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs new file mode 100644 index 000000000..43b2aec4b --- /dev/null +++ b/scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs @@ -0,0 +1,277 @@ +#!/usr/bin/env node + +import { execFileSync } from 'node:child_process'; +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const defaultRepoRoot = path.resolve(__dirname, '..'); +const ARTIFACT = '.bitcode/v34-distributed-execution-runtime-receipts.json'; + +const REQUIRED_WORK_KINDS = [ + 'pipeline_run', + 'ptrr_agent', + 'thricified_generation', + 'tool_call', + 'ledger_operation', + 'wallet_operation', + 'proof_generation', + 'object_storage_write', + 'repair_job', +]; + +const SECRET_MARKERS = [ + `${['sk', 'proj'].join('-')}-`, + `${['sb', 'secret'].join('_')}__`, + ['service', 'role'].join('_'), + ['eyJhbGciOiJI', 'UzI1NiIsInR5cCI6IkpXVCJ9'].join(''), + ['OPENAI', 'API', 'KEY'].join('_'), + ['VERCEL', 'TOKEN'].join('_'), + ['VERCEL', 'OIDC', 'TOKEN'].join('_'), + 'raw source', +]; + +function read(root, relativePath) { + return readFileSync(path.join(root, relativePath), 'utf8'); +} + +function fileExists(root, relativePath) { + return existsSync(path.join(root, relativePath)); +} + +function git(root, args) { + return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim(); +} + +function run(root, command, args) { + return execFileSync(command, args, { + cwd: root, + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], + }).trim(); +} + +function assertCheck(failures, condition, message) { + if (!condition) failures.push(message); +} + +function includesAll(values, requiredValues) { + return requiredValues.every((value) => values.includes(value)); +} + +function parseArgs(argv) { + const args = { + skipBranchCheck: false, + repoRoot: defaultRepoRoot, + }; + + for (let index = 0; index < argv.length; index += 1) { + const arg = argv[index]; + if (arg === '--skip-branch-check') args.skipBranchCheck = true; + else if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]); + else if (arg === '--help' || arg === '-h') args.help = true; + else throw new Error(`Unknown argument ${arg}`); + } + + return args; +} + +function printHelp() { + process.stdout.write( + [ + 'Usage: node scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs [--skip-branch-check] [--repo-root ]', + '', + 'Checks V34 Gate 3 Distributed Execution Runtime Contracts source, generated artifact, tests, docs, package scripts, and workflow wiring.', + ].join('\n'), + ); + process.stdout.write('\n'); +} + +function main() { + const args = parseArgs(process.argv.slice(2)); + if (args.help) { + printHelp(); + return; + } + + const root = args.repoRoot; + const failures = []; + const pointer = read(root, 'BITCODE_SPEC.txt').trim(); + + assertCheck( + failures, + pointer === 'V33', + `BITCODE_SPEC.txt must remain V33 during V34 gate work. Observed ${pointer || 'empty'}.`, + ); + + if (!args.skipBranchCheck) { + const branch = git(root, ['branch', '--show-current']); + assertCheck( + failures, + branch === 'version/v34' || /^v34\/gate-(?:[3-9]|10)-[a-z0-9][a-z0-9-]*$/u.test(branch), + `V34 Gate 3+ work must occur on version/v34 or v34/gate-3..10-* branches. Observed ${branch || 'detached HEAD'}.`, + ); + } + + const requiredFiles = [ + ARTIFACT, + 'packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts', + 'packages/pipeline-hosts/src/index.ts', + 'packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts', + 'scripts/generate-v34-distributed-execution-runtime-receipts.mjs', + 'scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs', + 'BITCODE_SPEC_V34.md', + 'BITCODE_SPEC_V34_DELTA.md', + 'BITCODE_SPEC_V34_NOTES.md', + 'BITCODE_SPEC_V34_PARITY_MATRIX.md', + 'SPECIFICATIONS_ROADMAP.md', + 'package.json', + '.github/workflows/bitcode-gate-quality.yml', + 'packages/protocol/src/canonical/v21-specifying.js', + ]; + + for (const relativePath of requiredFiles) { + assertCheck(failures, fileExists(root, relativePath), `Missing V34 Gate 3 file: ${relativePath}`); + } + + if (failures.length === 0) { + try { + run(root, 'pnpm', ['run', 'check:v34-distributed-execution-runtime-receipts']); + } catch (error) { + failures.push(`V34 Gate 3 artifact check failed: ${error.stderr || error.message}`); + } + } + + const serializedArtifact = fileExists(root, ARTIFACT) ? read(root, ARTIFACT) : ''; + for (const marker of SECRET_MARKERS) { + assertCheck(failures, !serializedArtifact.includes(marker), `V34 runtime receipt artifact must not contain secret/source marker ${marker}.`); + } + + const artifact = serializedArtifact ? JSON.parse(serializedArtifact) : null; + if (artifact) { + assertCheck(failures, artifact.artifactId === 'v34-distributed-execution-runtime-receipts', 'Artifact id must match Gate 3 receipts.'); + assertCheck(failures, artifact.schemaId === 'bitcode.v34.distributedExecutionRuntimeReceipts.v1', 'Artifact schema id must match.'); + assertCheck(failures, artifact.version === 'V34' && artifact.currentTarget === 'V33', 'Artifact must bind V34 over active V33.'); + assertCheck(failures, artifact.passed === true, 'Artifact must pass.'); + assertCheck( + failures, + artifact.sourceSafetyVerdict === 'source-safe-distributed-execution-runtime-receipts', + 'Artifact must be source-safe distributed execution receipt metadata.', + ); + assertCheck(failures, includesAll(artifact.requiredWorkKinds, REQUIRED_WORK_KINDS), 'Artifact must enumerate every required work kind.'); + assertCheck(failures, includesAll(artifact.coverage.observedWorkKinds, REQUIRED_WORK_KINDS), 'Artifact coverage must observe every work kind.'); + assertCheck(failures, artifact.coverage.workKindCount === 9, 'Artifact must prove nine receipt rows.'); + assertCheck( + failures, + artifact.coverage.routeHandlerRequiresSynchronousCompletion === false, + 'Long-running runtime work must not require request/response completion.', + ); + assertCheck(failures, artifact.coverage.inputRootsCovered === true, 'Input roots must be covered.'); + assertCheck(failures, artifact.coverage.outputRootsCovered === true, 'Output roots must be covered.'); + assertCheck(failures, artifact.coverage.logRootsCovered === true, 'Log roots must be covered.'); + assertCheck(failures, artifact.coverage.objectStorageRootsCovered === true, 'Object storage roots must be covered.'); + assertCheck(failures, artifact.coverage.ledgerProjectionRootsCovered === true, 'Ledger projection roots must be covered.'); + assertCheck(failures, artifact.coverage.databaseProjectionRootsCovered === true, 'Database projection roots must be covered.'); + assertCheck(failures, artifact.coverage.walletOperationRootsCovered === true, 'Wallet operation roots must be covered.'); + assertCheck(failures, artifact.coverage.proofRootsCovered === true, 'Proof roots must be covered.'); + assertCheck(failures, artifact.coverage.repairPostureCovered === true, 'Repair posture must be covered.'); + assertCheck(failures, artifact.coverage.ptrrAgentReceiptCovered === true, 'PTRR agent receipts must be covered.'); + assertCheck(failures, artifact.coverage.thricifiedGenerationReceiptCovered === true, 'ThricifiedGeneration receipts must be covered.'); + assertCheck(failures, artifact.coverage.toolCallReceiptCovered === true, 'Tool call receipts must be covered.'); + assertCheck(failures, artifact.coverage.credentialsSerialized === false, 'Artifact must not serialize credentials.'); + assertCheck(failures, artifact.coverage.protectedSourceVisible === false, 'Artifact must not expose protected source.'); + assertCheck( + failures, + artifact.receipts.every((receipt) => /^v34-distributed-execution-runtime-receipt:[a-f0-9]{24}$/u.test(receipt.receiptRoot)), + 'Receipt rows must have deterministic receipt roots.', + ); + assertCheck( + failures, + artifact.sourceEvidence.every((entry) => entry.requiredTokens.every((token) => token.present === true)), + 'Source evidence tokens must all be present.', + ); + assertCheck( + failures, + artifact.testEvidence.every((entry) => entry.requiredTokens.every((token) => token.present === true)), + 'Test evidence tokens must all be present.', + ); + } + + const spec = read(root, 'BITCODE_SPEC_V34.md'); + const delta = read(root, 'BITCODE_SPEC_V34_DELTA.md'); + const notes = read(root, 'BITCODE_SPEC_V34_NOTES.md'); + const parity = read(root, 'BITCODE_SPEC_V34_PARITY_MATRIX.md'); + const roadmap = read(root, 'SPECIFICATIONS_ROADMAP.md'); + const packageJson = read(root, 'package.json'); + const workflow = read(root, '.github/workflows/bitcode-gate-quality.yml'); + const source = read(root, 'packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts'); + const test = read(root, 'packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts'); + const specifying = read(root, 'packages/protocol/src/canonical/v21-specifying.js'); + + for (const doc of [spec, delta, notes, parity]) { + assertCheck(failures, doc.includes(ARTIFACT), `V34 docs must mention ${ARTIFACT}.`); + assertCheck(failures, doc.includes('DistributedExecutionRuntimeReceipt'), 'V34 docs must name DistributedExecutionRuntimeReceipt.'); + assertCheck(failures, doc.includes('request_response_not_required'), 'V34 docs must name request_response_not_required.'); + assertCheck(failures, doc.includes('ptrr_agent'), 'V34 docs must name ptrr_agent receipt work.'); + assertCheck(failures, doc.includes('thricified_generation'), 'V34 docs must name thricified_generation receipt work.'); + assertCheck(failures, doc.includes('object_storage_write'), 'V34 docs must name object_storage_write receipt work.'); + assertCheck(failures, doc.includes('repair_job'), 'V34 docs must name repair_job receipt work.'); + } + + assertCheck( + failures, + /Current working gate: V34 Gate (?:[4-9]|10)\b/u.test(roadmap), + 'Roadmap must advance past V34 Gate 3 after this gate closes.', + ); + assertCheck(failures, packageJson.includes('"generate:v34-distributed-execution-runtime-receipts"'), 'package.json must expose the Gate 3 generator.'); + assertCheck(failures, packageJson.includes('"check:v34-distributed-execution-runtime-receipts"'), 'package.json must expose the Gate 3 artifact check.'); + assertCheck(failures, packageJson.includes('"check:v34-gate3"'), 'package.json must expose check:v34-gate3.'); + assertCheck(failures, workflow.includes('check-v34-gate3-distributed-execution-runtime-contracts.mjs'), 'Gate workflow must run the V34 Gate 3 checker.'); + assertCheck(failures, workflow.includes('distributed-execution-runtime-receipt.test.ts'), 'Gate workflow must run the focused distributed execution receipt test.'); + assertCheck(failures, specifying.includes(ARTIFACT), 'Spec-family profile must include the Gate 3 artifact path.'); + + for (const phrase of [ + 'DistributedExecutionRuntimeReceipt', + 'DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS', + 'request_response_not_required', + 'blocking_allowed_for_short_local_work', + 'ptrr_agent', + 'thricified_generation', + 'tool_call', + 'ledger_operation', + 'wallet_operation', + 'proof_generation', + 'object_storage_write', + 'repair_job', + ]) { + assertCheck(failures, source.includes(phrase), `Gate 3 source must include ${phrase}.`); + } + + for (const phrase of [ + 'catalogs pipeline runs, PTRR agents, ThricifiedGenerations, tool calls, ledger operations, wallet operations, proof generation, object-storage writes, and repair jobs', + 'keeps long-running runtime work detached from request/response route handler completion', + 'covers required roots for pipeline, tool, ledger, wallet, proof, storage, and repair receipts', + 'fails closed when successful runtime receipts omit output roots', + 'fails closed when PTRR and ThricifiedGeneration receipts omit formal step data', + 'fails closed when tool, ledger, wallet, proof, storage, and repair receipts omit their owned roots', + 'fails closed on secret-shaped or protected-source receipt text', + ]) { + assertCheck(failures, test.includes(phrase), `Gate 3 test must assert: ${phrase}.`); + } + + if (failures.length) { + process.stderr.write('V34 Gate 3 Distributed Execution Runtime Contracts check failed:\n'); + for (const failure of failures) { + process.stderr.write(`- ${failure}\n`); + } + process.exit(1); + } + + process.stdout.write('V34 Gate 3 Distributed Execution Runtime Contracts check passed.\n'); +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main(); +} diff --git a/scripts/generate-v34-distributed-execution-runtime-receipts.mjs b/scripts/generate-v34-distributed-execution-runtime-receipts.mjs new file mode 100644 index 000000000..693708bdb --- /dev/null +++ b/scripts/generate-v34-distributed-execution-runtime-receipts.mjs @@ -0,0 +1,465 @@ +#!/usr/bin/env node + +import { createHash } from 'node:crypto'; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); +const ARTIFACT_PATH = '.bitcode/v34-distributed-execution-runtime-receipts.json'; +const GENERATED_AT = '2026-05-22T00:00:00.000Z'; + +const SECRET_MARKERS = Object.freeze([ + `${['sk', 'proj'].join('-')}-`, + `${['sb', 'secret'].join('_')}__`, + ['service', 'role'].join('_'), + ['eyJhbGciOiJI', 'UzI1NiIsInR5cCI6IkpXVCJ9'].join(''), + ['SUPABASE', 'SERVICE', 'ROLE'].join('_'), + ['OPENAI', 'API', 'KEY'].join('_'), + ['VERCEL', 'TOKEN'].join('_'), + ['VERCEL', 'OIDC', 'TOKEN'].join('_'), + 'raw source', +]); +const SECRET_PATTERN = new RegExp(SECRET_MARKERS.map(escapeRegex).join('|'), 'iu'); + +const requiredWorkKinds = Object.freeze([ + 'pipeline_run', + 'ptrr_agent', + 'thricified_generation', + 'tool_call', + 'ledger_operation', + 'wallet_operation', + 'proof_generation', + 'object_storage_write', + 'repair_job', +]); + +const receiptRows = Object.freeze([ + { + executionId: 'execution-read-fits-finding-synthesis', + hostId: 'pipeline_workers', + laneId: 'staging-testnet', + workKind: 'pipeline_run', + commandOrPipelineId: 'ReadFitsFindingSynthesis', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + phaseId: 'discovery', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:pipeline-input-root', + outputRoot: 'sha256:pipeline-output-root', + logRoot: 'sha256:runtime-log-root', + objectStorageRoot: 'sha256:pipeline-object-storage-root', + ledgerProjectionRoot: 'sha256:pipeline-ledger-projection-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:pipeline-proof-root', + repairPosture: 'retry-detached-pipeline-from-input-root', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-read-fits-agent', + hostId: 'pipeline_workers', + laneId: 'staging-testnet', + workKind: 'ptrr_agent', + commandOrPipelineId: 'ReadFitsFindingSynthesisDiscoveryAgent', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'plan', + parentReceiptRoot: 'receipt:pipeline-run-root', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:agent-input-root', + outputRoot: 'sha256:agent-output-root', + logRoot: 'sha256:runtime-log-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:agent-proof-root', + repairPosture: 'resume-ptrr-agent-from-step-root', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-thricified-generation', + hostId: 'pipeline_workers', + laneId: 'staging-testnet', + workKind: 'thricified_generation', + commandOrPipelineId: 'ReadFitsFindingSynthesisDiscoveryAgent.plan.reason', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'plan', + thricifiedGenerationStep: 'reason', + parentReceiptRoot: 'receipt:ptrr-agent-root', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:generation-input-root', + outputRoot: 'sha256:generation-output-root', + logRoot: 'sha256:runtime-log-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:generation-proof-root', + repairPosture: 'regenerate-from-redacted-prompt-and-context-root', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-depository-search-tool', + hostId: 'pipeline_workers', + laneId: 'staging-testnet', + workKind: 'tool_call', + commandOrPipelineId: 'AssetPackLexicalDepositorySearchTool', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + phaseId: 'discovery', + agentId: 'ReadFitsFindingSynthesisDiscoveryAgent', + ptrrStep: 'try', + toolId: 'AssetPackLexicalDepositorySearchTool', + parentReceiptRoot: 'receipt:thricified-generation-root', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:tool-input-root', + outputRoot: 'sha256:tool-output-root', + logRoot: 'sha256:runtime-log-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:tool-proof-root', + repairPosture: 'rerun-tool-from-input-root-with-source-safe-query', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-ledger-operation', + hostId: 'ledger_projection', + laneId: 'staging-testnet', + workKind: 'ledger_operation', + commandOrPipelineId: 'ledger.project.read-rights', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:ledger-input-root', + outputRoot: 'sha256:ledger-output-root', + logRoot: 'sha256:runtime-log-root', + ledgerProjectionRoot: 'sha256:ledger-projection-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:ledger-proof-root', + repairPosture: 'hold-unlock-and-replay-ledger-projection', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-wallet-operation', + hostId: 'ledger_broadcasters', + laneId: 'signet', + workKind: 'wallet_operation', + commandOrPipelineId: 'btc.fee.sign-and-broadcast', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:wallet-input-root', + outputRoot: 'sha256:wallet-output-root', + logRoot: 'sha256:runtime-log-root', + databaseProjectionRoot: 'sha256:database-projection-root', + walletOperationRoot: 'sha256:wallet-operation-root', + proofRoot: 'sha256:wallet-proof-root', + repairPosture: 'deny-broadcast-until-wallet-policy-repaired', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-proof-generation', + hostId: 'proof_services', + laneId: 'staging-testnet', + workKind: 'proof_generation', + commandOrPipelineId: 'deployment.proof.generate', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:proof-input-root', + outputRoot: 'sha256:proof-output-root', + logRoot: 'sha256:runtime-log-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:proof-generation-root', + repairPosture: 'regenerate-proof-from-canonical-inputs', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-object-storage-write', + hostId: 'object_storage', + laneId: 'staging-testnet', + workKind: 'object_storage_write', + commandOrPipelineId: 'assetpack.preview.persist', + status: 'succeeded', + routeHandlerBoundary: 'request_response_not_required', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:object-storage-input-root', + outputRoot: 'sha256:object-storage-output-root', + logRoot: 'sha256:runtime-log-root', + objectStorageRoot: 'sha256:object-storage-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:object-storage-proof-root', + repairPosture: 'lock-delivery-and-rewrite-from-authorized-artifact-root', + replayCommand: 'pnpm run check:v34-gate3', + }, + { + executionId: 'execution-repair-job', + hostId: 'repair_jobs', + laneId: 'staging-testnet', + workKind: 'repair_job', + commandOrPipelineId: 'projection.repair', + status: 'repaired', + routeHandlerBoundary: 'request_response_not_required', + startedAt: '2026-05-22T00:00:00.000Z', + completedAt: '2026-05-22T00:00:01.000Z', + inputRoot: 'sha256:repair-input-root', + outputRoot: 'sha256:repair-output-root', + logRoot: 'sha256:runtime-log-root', + objectStorageRoot: 'sha256:repair-object-storage-root', + ledgerProjectionRoot: 'sha256:repair-ledger-projection-root', + databaseProjectionRoot: 'sha256:database-projection-root', + proofRoot: 'sha256:repair-proof-root', + repairPosture: 'repair-complete-with-replayable-proof-root', + replayCommand: 'pnpm run check:v34-gate3', + }, +]); + +const sourceFiles = Object.freeze([ + 'packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts', + 'packages/pipeline-hosts/src/index.ts', + 'BITCODE_SPEC_V34.md', + 'BITCODE_SPEC_V34_DELTA.md', + 'BITCODE_SPEC_V34_PARITY_MATRIX.md', +]); + +const testFiles = Object.freeze([ + 'packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts', + 'scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs', +]); + +function escapeRegex(value) { + return value.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&'); +} + +function read(relativePath) { + return readFileSync(path.join(repoRoot, relativePath), 'utf8'); +} + +function sha256(value) { + return `sha256:${createHash('sha256').update(value).digest('hex')}`; +} + +function stableRoot(prefix, parts) { + const hash = createHash('sha256').update(parts.join('\u001f')).digest('hex').slice(0, 24); + return `${prefix}:${hash}`; +} + +function sortJson(value) { + if (Array.isArray(value)) return value.map(sortJson); + if (!value || typeof value !== 'object') return value; + return Object.fromEntries( + Object.entries(value) + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, entry]) => [key, sortJson(entry)]), + ); +} + +function stableStringify(value) { + return `${JSON.stringify(sortJson(value), null, 2)}\n`; +} + +function scanTokens(relativePath, tokens) { + const text = read(relativePath); + return { + relativePath, + digest: sha256(text), + requiredTokens: tokens.map((token) => ({ + token, + present: text.includes(token), + })), + }; +} + +function allTokensPresent(scan) { + return scan.requiredTokens.every((entry) => entry.present); +} + +function withReceiptRoots(rows) { + return rows.map((row) => ({ + ...row, + credentialsSerialized: false, + protectedSourceVisible: false, + sourceSafety: { + sourceSafe: true, + protectedSourceVisible: false, + containsProtectedSource: false, + containsSecret: false, + credentialsSerialized: false, + }, + receiptRoot: stableRoot('v34-distributed-execution-runtime-receipt', [ + row.executionId, + row.hostId, + row.laneId, + row.workKind, + row.commandOrPipelineId, + row.status, + row.routeHandlerBoundary, + row.inputRoot, + row.outputRoot, + row.logRoot, + row.objectStorageRoot ?? 'no-object-storage-root', + row.ledgerProjectionRoot ?? 'no-ledger-root', + row.databaseProjectionRoot ?? 'no-database-root', + row.walletOperationRoot ?? 'no-wallet-root', + row.proofRoot ?? 'no-proof-root', + row.repairPosture, + ]), + })); +} + +export function buildV34DistributedExecutionRuntimeReceiptsArtifact() { + const receipts = withReceiptRoots(receiptRows); + const observedWorkKinds = [...new Set(receipts.map((receipt) => receipt.workKind))].sort(); + const missingWorkKinds = requiredWorkKinds.filter( + (workKind) => !observedWorkKinds.includes(workKind), + ); + const routeHandlerRequiresSynchronousCompletion = receipts.some( + (receipt) => receipt.routeHandlerBoundary !== 'request_response_not_required', + ); + const sourceEvidence = [ + scanTokens('packages/pipeline-hosts/src/distributed-execution-runtime-receipt.ts', [ + 'DistributedExecutionRuntimeReceipt', + 'DISTRIBUTED_EXECUTION_RUNTIME_WORK_KINDS', + 'request_response_not_required', + 'ptrr_agent', + 'thricified_generation', + 'object_storage_write', + 'repair_job', + ]), + scanTokens('packages/pipeline-hosts/src/index.ts', [ + 'distributed-execution-runtime-receipt', + ]), + scanTokens('BITCODE_SPEC_V34.md', [ + ARTIFACT_PATH, + 'DistributedExecutionRuntimeReceipt', + 'request_response_not_required', + ]), + ]; + const testEvidence = [ + scanTokens('packages/pipeline-hosts/src/__tests__/distributed-execution-runtime-receipt.test.ts', [ + 'catalogs pipeline runs, PTRR agents, ThricifiedGenerations, tool calls, ledger operations, wallet operations, proof generation, object-storage writes, and repair jobs', + 'keeps long-running runtime work detached from request/response route handler completion', + 'covers required roots for pipeline, tool, ledger, wallet, proof, storage, and repair receipts', + 'fails closed when successful runtime receipts omit output roots', + 'fails closed on secret-shaped or protected-source receipt text', + ]), + scanTokens('scripts/check-v34-gate3-distributed-execution-runtime-contracts.mjs', [ + 'check:v34-distributed-execution-runtime-receipts', + 'distributed-execution-runtime-receipt.test.ts', + 'Distributed Execution Runtime Contracts', + ]), + ]; + const sourceEvidenceComplete = sourceEvidence.every(allTokensPresent); + const testEvidenceComplete = testEvidence.every(allTokensPresent); + const passed = + missingWorkKinds.length === 0 && + receipts.length === requiredWorkKinds.length && + routeHandlerRequiresSynchronousCompletion === false && + sourceEvidenceComplete && + testEvidenceComplete; + + return { + artifactId: 'v34-distributed-execution-runtime-receipts', + schemaId: 'bitcode.v34.distributedExecutionRuntimeReceipts.v1', + version: 'V34', + currentTarget: 'V33', + generatedAt: GENERATED_AT, + sourceSafetyVerdict: 'source-safe-distributed-execution-runtime-receipts', + requiredWorkKinds, + receiptCatalogRoot: stableRoot( + 'v34-distributed-execution-runtime-receipts', + receipts.map((receipt) => receipt.receiptRoot), + ), + receipts, + coverage: { + observedWorkKinds, + missingWorkKinds, + workKindCount: receipts.length, + routeHandlerRequiresSynchronousCompletion, + requestResponseCompletionRequired: false, + inputRootsCovered: receipts.every((receipt) => Boolean(receipt.inputRoot)), + outputRootsCovered: receipts.every((receipt) => Boolean(receipt.outputRoot)), + logRootsCovered: receipts.every((receipt) => Boolean(receipt.logRoot)), + objectStorageRootsCovered: receipts.some((receipt) => Boolean(receipt.objectStorageRoot)), + ledgerProjectionRootsCovered: receipts.some((receipt) => + Boolean(receipt.ledgerProjectionRoot), + ), + databaseProjectionRootsCovered: receipts.every((receipt) => + Boolean(receipt.databaseProjectionRoot), + ), + walletOperationRootsCovered: receipts.some((receipt) => + Boolean(receipt.walletOperationRoot), + ), + proofRootsCovered: receipts.some((receipt) => Boolean(receipt.proofRoot)), + repairPostureCovered: receipts.every((receipt) => Boolean(receipt.repairPosture)), + ptrrAgentReceiptCovered: observedWorkKinds.includes('ptrr_agent'), + thricifiedGenerationReceiptCovered: observedWorkKinds.includes('thricified_generation'), + toolCallReceiptCovered: observedWorkKinds.includes('tool_call'), + protectedSourceVisible: false, + credentialsSerialized: false, + }, + sharedFixtureFiles: [...sourceFiles, ...testFiles], + sourceEvidence, + testEvidence, + passed, + closureCommand: 'pnpm run check:v34-gate3', + }; +} + +function assertSafeArtifact(artifact) { + const serialized = stableStringify(artifact); + if (SECRET_PATTERN.test(serialized)) { + throw new Error(`${ARTIFACT_PATH} contains a secret-shaped marker or protected source marker.`); + } + if (!artifact.passed) { + throw new Error(`${ARTIFACT_PATH} source or test evidence is incomplete.`); + } + + return serialized; +} + +function writeArtifact(artifact) { + const serialized = assertSafeArtifact(artifact); + mkdirSync(path.dirname(path.join(repoRoot, ARTIFACT_PATH)), { recursive: true }); + writeFileSync(path.join(repoRoot, ARTIFACT_PATH), serialized); + return serialized; +} + +function checkArtifact(artifact) { + const next = assertSafeArtifact(artifact); + const artifactFile = path.join(repoRoot, ARTIFACT_PATH); + if (!existsSync(artifactFile)) { + throw new Error(`${ARTIFACT_PATH} is missing. Run pnpm run generate:v34-distributed-execution-runtime-receipts.`); + } + const current = readFileSync(artifactFile, 'utf8'); + if (current !== next) { + throw new Error(`${ARTIFACT_PATH} is stale. Run pnpm run generate:v34-distributed-execution-runtime-receipts.`); + } +} + +function main() { + const mode = process.argv.includes('--check') ? 'check' : 'write'; + const artifact = buildV34DistributedExecutionRuntimeReceiptsArtifact(); + + if (mode === 'check') { + checkArtifact(artifact); + process.stdout.write(`V34 distributed execution runtime receipts artifact ok ${ARTIFACT_PATH}\n`); + return; + } + + writeArtifact(artifact); + process.stdout.write(`Wrote ${ARTIFACT_PATH}\n`); +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main(); +}