open-multi-agent-kit 0.98.3 → 0.98.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +12 -2
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +14 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +3 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/mcp-attach.d.ts +3 -3
- package/dist/cli/mcp-attach.d.ts.map +1 -1
- package/dist/cli/mcp-attach.js +5 -4
- package/dist/cli/mcp-attach.js.map +1 -1
- package/dist/cli/model-contract.d.ts +5 -0
- package/dist/cli/model-contract.d.ts.map +1 -0
- package/dist/cli/model-contract.js +45 -0
- package/dist/cli/model-contract.js.map +1 -0
- package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -1
- package/dist/commands/adaptorch-doctor-cli.js +32 -10
- package/dist/commands/adaptorch-doctor-cli.js.map +1 -1
- package/dist/commands/init-cli.d.ts +12 -0
- package/dist/commands/init-cli.d.ts.map +1 -0
- package/dist/commands/init-cli.js +76 -0
- package/dist/commands/init-cli.js.map +1 -0
- package/dist/commands/provider-sync-cli.d.ts +27 -0
- package/dist/commands/provider-sync-cli.d.ts.map +1 -0
- package/dist/commands/provider-sync-cli.js +177 -0
- package/dist/commands/provider-sync-cli.js.map +1 -0
- package/dist/commands/run-command.d.ts +9 -0
- package/dist/commands/run-command.d.ts.map +1 -0
- package/dist/commands/run-command.js +34 -0
- package/dist/commands/run-command.js.map +1 -0
- package/dist/commands/verified-run-cli.d.ts +6 -0
- package/dist/commands/verified-run-cli.d.ts.map +1 -0
- package/dist/commands/verified-run-cli.js +190 -0
- package/dist/commands/verified-run-cli.js.map +1 -0
- package/dist/core/active-skill-state.d.ts +7 -0
- package/dist/core/active-skill-state.d.ts.map +1 -0
- package/dist/core/active-skill-state.js +25 -0
- package/dist/core/active-skill-state.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +10 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +43 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +7 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +91 -126
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
- package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
- package/dist/core/codex-chatgpt-web-bridge.js +192 -0
- package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
- package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
- package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
- package/dist/core/codex-chatgpt-web-sync.js +119 -0
- package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
- package/dist/core/compaction/compaction-headroom.d.ts +30 -0
- package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
- package/dist/core/compaction/compaction-headroom.js +48 -0
- package/dist/core/compaction/compaction-headroom.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +2 -29
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +19 -47
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
- package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
- package/dist/core/compaction/overflow-retry-guard.js +38 -0
- package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
- package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-types.js +1 -1
- package/dist/core/context-budget-headroom-types.js.map +1 -1
- package/dist/core/context-budget-token-counter-types.d.ts +27 -0
- package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
- package/dist/core/context-budget-token-counter-types.js +2 -0
- package/dist/core/context-budget-token-counter-types.js.map +1 -0
- package/dist/core/context-budget-token-counter.d.ts +2 -26
- package/dist/core/context-budget-token-counter.d.ts.map +1 -1
- package/dist/core/context-budget-token-counter.js +2 -0
- package/dist/core/context-budget-token-counter.js.map +1 -1
- package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
- package/dist/core/context-budget-v2-scoring.js +14 -10
- package/dist/core/context-budget-v2-scoring.js.map +1 -1
- package/dist/core/domain-router.d.ts.map +1 -1
- package/dist/core/domain-router.js +1 -1
- package/dist/core/domain-router.js.map +1 -1
- package/dist/core/grok-harness-dispatch.d.ts +4 -0
- package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
- package/dist/core/grok-harness-dispatch.js +20 -3
- package/dist/core/grok-harness-dispatch.js.map +1 -1
- package/dist/core/grok-harness.d.ts +15 -9
- package/dist/core/grok-harness.d.ts.map +1 -1
- package/dist/core/grok-harness.js +34 -8
- package/dist/core/grok-harness.js.map +1 -1
- package/dist/core/mcp/tools.d.ts +2 -2
- package/dist/core/mcp/tools.d.ts.map +1 -1
- package/dist/core/mcp/tools.js +29 -3
- package/dist/core/mcp/tools.js.map +1 -1
- package/dist/core/model-registry-schema.d.ts +1081 -0
- package/dist/core/model-registry-schema.d.ts.map +1 -0
- package/dist/core/model-registry-schema.js +148 -0
- package/dist/core/model-registry-schema.js.map +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -146
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/prompt-preset.d.ts +1 -1
- package/dist/core/prompt-preset.d.ts.map +1 -1
- package/dist/core/prompt-preset.js +16 -1
- package/dist/core/prompt-preset.js.map +1 -1
- package/dist/core/prompt-settlement.d.ts +4 -3
- package/dist/core/prompt-settlement.d.ts.map +1 -1
- package/dist/core/prompt-settlement.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +8 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +20 -3
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/provider-usage-types.d.ts +42 -0
- package/dist/core/provider-usage-types.d.ts.map +1 -0
- package/dist/core/provider-usage-types.js +2 -0
- package/dist/core/provider-usage-types.js.map +1 -0
- package/dist/core/provider-usage.d.ts +2 -31
- package/dist/core/provider-usage.d.ts.map +1 -1
- package/dist/core/provider-usage.js +4 -0
- package/dist/core/provider-usage.js.map +1 -1
- package/dist/core/redaction.d.ts.map +1 -1
- package/dist/core/redaction.js +18 -2
- package/dist/core/redaction.js.map +1 -1
- package/dist/core/run-budget-policy.d.ts +18 -0
- package/dist/core/run-budget-policy.d.ts.map +1 -0
- package/dist/core/run-budget-policy.js +52 -0
- package/dist/core/run-budget-policy.js.map +1 -0
- package/dist/core/run-budget.d.ts +33 -0
- package/dist/core/run-budget.d.ts.map +1 -0
- package/dist/core/run-budget.js +89 -0
- package/dist/core/run-budget.js.map +1 -0
- package/dist/core/run-execution-api.d.ts +15 -0
- package/dist/core/run-execution-api.d.ts.map +1 -0
- package/dist/core/run-execution-api.js +7 -0
- package/dist/core/run-execution-api.js.map +1 -0
- package/dist/core/run-journal.d.ts.map +1 -1
- package/dist/core/run-journal.js +30 -208
- package/dist/core/run-journal.js.map +1 -1
- package/dist/core/sandbox/policy-merge.d.ts +6 -0
- package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
- package/dist/core/sandbox/policy-merge.js +74 -0
- package/dist/core/sandbox/policy-merge.js.map +1 -0
- package/dist/core/sandbox/policy-paths.d.ts +4 -0
- package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
- package/dist/core/sandbox/policy-paths.js +21 -0
- package/dist/core/sandbox/policy-paths.js.map +1 -0
- package/dist/core/sandbox/policy-types.d.ts +75 -0
- package/dist/core/sandbox/policy-types.d.ts.map +1 -0
- package/dist/core/sandbox/policy-types.js +2 -0
- package/dist/core/sandbox/policy-types.js.map +1 -0
- package/dist/core/sandbox/policy.d.ts +3 -77
- package/dist/core/sandbox/policy.d.ts.map +1 -1
- package/dist/core/sandbox/policy.js +3 -98
- package/dist/core/sandbox/policy.js.map +1 -1
- package/dist/core/sdk-provider-stream.d.ts +14 -0
- package/dist/core/sdk-provider-stream.d.ts.map +1 -0
- package/dist/core/sdk-provider-stream.js +38 -0
- package/dist/core/sdk-provider-stream.js.map +1 -0
- package/dist/core/sdk.d.ts +5 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +17 -33
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-bash-service.d.ts +2 -2
- package/dist/core/session-bash-service.d.ts.map +1 -1
- package/dist/core/session-bash-service.js +21 -9
- package/dist/core/session-bash-service.js.map +1 -1
- package/dist/core/session-failure-cause.d.ts.map +1 -1
- package/dist/core/session-failure-cause.js +15 -3
- package/dist/core/session-failure-cause.js.map +1 -1
- package/dist/core/session-prompt-lifecycle.d.ts +25 -0
- package/dist/core/session-prompt-lifecycle.d.ts.map +1 -0
- package/dist/core/session-prompt-lifecycle.js +87 -0
- package/dist/core/session-prompt-lifecycle.js.map +1 -0
- package/dist/core/session-run-budget.d.ts +28 -0
- package/dist/core/session-run-budget.d.ts.map +1 -0
- package/dist/core/session-run-budget.js +127 -0
- package/dist/core/session-run-budget.js.map +1 -0
- package/dist/core/session-run-termination.d.ts +18 -0
- package/dist/core/session-run-termination.d.ts.map +1 -0
- package/dist/core/session-run-termination.js +72 -0
- package/dist/core/session-run-termination.js.map +1 -0
- package/dist/core/session-termination-types.d.ts +97 -0
- package/dist/core/session-termination-types.d.ts.map +1 -0
- package/dist/core/session-termination-types.js +26 -0
- package/dist/core/session-termination-types.js.map +1 -0
- package/dist/core/session-termination.d.ts +3 -97
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +25 -29
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/skill-selector.d.ts +40 -0
- package/dist/core/skill-selector.d.ts.map +1 -0
- package/dist/core/skill-selector.js +102 -0
- package/dist/core/skill-selector.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/subagent-lane-launcher.d.ts +3 -2
- package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
- package/dist/core/subagent-lane-launcher.js +24 -13
- package/dist/core/subagent-lane-launcher.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +2 -4
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/turn-metrics-record.d.ts +55 -0
- package/dist/core/turn-metrics-record.d.ts.map +1 -0
- package/dist/core/turn-metrics-record.js +149 -0
- package/dist/core/turn-metrics-record.js.map +1 -0
- package/dist/core/turn-metrics.d.ts +4 -56
- package/dist/core/turn-metrics.d.ts.map +1 -1
- package/dist/core/turn-metrics.js +12 -60
- package/dist/core/turn-metrics.js.map +1 -1
- package/dist/core/verified-run/broker.d.ts +26 -0
- package/dist/core/verified-run/broker.d.ts.map +1 -0
- package/dist/core/verified-run/broker.js +210 -0
- package/dist/core/verified-run/broker.js.map +1 -0
- package/dist/core/verified-run/candidate.d.ts +24 -0
- package/dist/core/verified-run/candidate.d.ts.map +1 -0
- package/dist/core/verified-run/candidate.js +167 -0
- package/dist/core/verified-run/candidate.js.map +1 -0
- package/dist/core/verified-run/check-receipt.d.ts +18 -0
- package/dist/core/verified-run/check-receipt.d.ts.map +1 -0
- package/dist/core/verified-run/check-receipt.js +92 -0
- package/dist/core/verified-run/check-receipt.js.map +1 -0
- package/dist/core/verified-run/coordinator.d.ts +39 -0
- package/dist/core/verified-run/coordinator.d.ts.map +1 -0
- package/dist/core/verified-run/coordinator.js +190 -0
- package/dist/core/verified-run/coordinator.js.map +1 -0
- package/dist/core/verified-run/dag-candidates.d.ts +8 -0
- package/dist/core/verified-run/dag-candidates.d.ts.map +1 -0
- package/dist/core/verified-run/dag-candidates.js +65 -0
- package/dist/core/verified-run/dag-candidates.js.map +1 -0
- package/dist/core/verified-run/dag-phase.d.ts +7 -0
- package/dist/core/verified-run/dag-phase.d.ts.map +1 -0
- package/dist/core/verified-run/dag-phase.js +92 -0
- package/dist/core/verified-run/dag-phase.js.map +1 -0
- package/dist/core/verified-run/dag-projection.d.ts +7 -0
- package/dist/core/verified-run/dag-projection.d.ts.map +1 -0
- package/dist/core/verified-run/dag-projection.js +90 -0
- package/dist/core/verified-run/dag-projection.js.map +1 -0
- package/dist/core/verified-run/dag-recovery.d.ts +13 -0
- package/dist/core/verified-run/dag-recovery.d.ts.map +1 -0
- package/dist/core/verified-run/dag-recovery.js +98 -0
- package/dist/core/verified-run/dag-recovery.js.map +1 -0
- package/dist/core/verified-run/dag-retry-projection.d.ts +9 -0
- package/dist/core/verified-run/dag-retry-projection.d.ts.map +1 -0
- package/dist/core/verified-run/dag-retry-projection.js +43 -0
- package/dist/core/verified-run/dag-retry-projection.js.map +1 -0
- package/dist/core/verified-run/dag-types.d.ts +47 -0
- package/dist/core/verified-run/dag-types.d.ts.map +1 -0
- package/dist/core/verified-run/dag-types.js +2 -0
- package/dist/core/verified-run/dag-types.js.map +1 -0
- package/dist/core/verified-run/event-parser.d.ts +3 -0
- package/dist/core/verified-run/event-parser.d.ts.map +1 -0
- package/dist/core/verified-run/event-parser.js +153 -0
- package/dist/core/verified-run/event-parser.js.map +1 -0
- package/dist/core/verified-run/events.d.ts +4 -0
- package/dist/core/verified-run/events.d.ts.map +1 -0
- package/dist/core/verified-run/events.js +3 -0
- package/dist/core/verified-run/events.js.map +1 -0
- package/dist/core/verified-run/evidence-binding.d.ts +18 -0
- package/dist/core/verified-run/evidence-binding.d.ts.map +1 -0
- package/dist/core/verified-run/evidence-binding.js +81 -0
- package/dist/core/verified-run/evidence-binding.js.map +1 -0
- package/dist/core/verified-run/evidence.d.ts +27 -0
- package/dist/core/verified-run/evidence.d.ts.map +1 -0
- package/dist/core/verified-run/evidence.js +100 -0
- package/dist/core/verified-run/evidence.js.map +1 -0
- package/dist/core/verified-run/journal.d.ts +32 -0
- package/dist/core/verified-run/journal.d.ts.map +1 -0
- package/dist/core/verified-run/journal.js +103 -0
- package/dist/core/verified-run/journal.js.map +1 -0
- package/dist/core/verified-run/namespace-identity.d.ts +11 -0
- package/dist/core/verified-run/namespace-identity.d.ts.map +1 -0
- package/dist/core/verified-run/namespace-identity.js +77 -0
- package/dist/core/verified-run/namespace-identity.js.map +1 -0
- package/dist/core/verified-run/owned-execution.d.ts +21 -0
- package/dist/core/verified-run/owned-execution.d.ts.map +1 -0
- package/dist/core/verified-run/owned-execution.js +43 -0
- package/dist/core/verified-run/owned-execution.js.map +1 -0
- package/dist/core/verified-run/phase-context.d.ts +9 -0
- package/dist/core/verified-run/phase-context.d.ts.map +1 -0
- package/dist/core/verified-run/phase-context.js +2 -0
- package/dist/core/verified-run/phase-context.js.map +1 -0
- package/dist/core/verified-run/process-gate.d.ts +5 -0
- package/dist/core/verified-run/process-gate.d.ts.map +1 -0
- package/dist/core/verified-run/process-gate.js +31 -0
- package/dist/core/verified-run/process-gate.js.map +1 -0
- package/dist/core/verified-run/projection.d.ts +4 -0
- package/dist/core/verified-run/projection.d.ts.map +1 -0
- package/dist/core/verified-run/projection.js +219 -0
- package/dist/core/verified-run/projection.js.map +1 -0
- package/dist/core/verified-run/recovery-clock.d.ts +19 -0
- package/dist/core/verified-run/recovery-clock.d.ts.map +1 -0
- package/dist/core/verified-run/recovery-clock.js +69 -0
- package/dist/core/verified-run/recovery-clock.js.map +1 -0
- package/dist/core/verified-run/recovery-command.d.ts +11 -0
- package/dist/core/verified-run/recovery-command.d.ts.map +1 -0
- package/dist/core/verified-run/recovery-command.js +73 -0
- package/dist/core/verified-run/recovery-command.js.map +1 -0
- package/dist/core/verified-run/recovery-projection.d.ts +12 -0
- package/dist/core/verified-run/recovery-projection.d.ts.map +1 -0
- package/dist/core/verified-run/recovery-projection.js +88 -0
- package/dist/core/verified-run/recovery-projection.js.map +1 -0
- package/dist/core/verified-run/recovery.d.ts +12 -0
- package/dist/core/verified-run/recovery.d.ts.map +1 -0
- package/dist/core/verified-run/recovery.js +115 -0
- package/dist/core/verified-run/recovery.js.map +1 -0
- package/dist/core/verified-run/run-types.d.ts +103 -0
- package/dist/core/verified-run/run-types.d.ts.map +1 -0
- package/dist/core/verified-run/run-types.js +2 -0
- package/dist/core/verified-run/run-types.js.map +1 -0
- package/dist/core/verified-run/scripted-writer.d.ts +15 -0
- package/dist/core/verified-run/scripted-writer.d.ts.map +1 -0
- package/dist/core/verified-run/scripted-writer.js +94 -0
- package/dist/core/verified-run/scripted-writer.js.map +1 -0
- package/dist/core/verified-run/session-port.d.ts +27 -0
- package/dist/core/verified-run/session-port.d.ts.map +1 -0
- package/dist/core/verified-run/session-port.js +2 -0
- package/dist/core/verified-run/session-port.js.map +1 -0
- package/dist/core/verified-run/storage.d.ts +15 -0
- package/dist/core/verified-run/storage.d.ts.map +1 -0
- package/dist/core/verified-run/storage.js +96 -0
- package/dist/core/verified-run/storage.js.map +1 -0
- package/dist/core/verified-run/verification-phase.d.ts +5 -0
- package/dist/core/verified-run/verification-phase.d.ts.map +1 -0
- package/dist/core/verified-run/verification-phase.js +56 -0
- package/dist/core/verified-run/verification-phase.js.map +1 -0
- package/dist/core/verified-run/work-recovery.d.ts +8 -0
- package/dist/core/verified-run/work-recovery.d.ts.map +1 -0
- package/dist/core/verified-run/work-recovery.js +44 -0
- package/dist/core/verified-run/work-recovery.js.map +1 -0
- package/dist/core/verified-run/writer-completion.d.ts +4 -0
- package/dist/core/verified-run/writer-completion.d.ts.map +1 -0
- package/dist/core/verified-run/writer-completion.js +27 -0
- package/dist/core/verified-run/writer-completion.js.map +1 -0
- package/dist/core/verified-run/writer-phase.d.ts +8 -0
- package/dist/core/verified-run/writer-phase.d.ts.map +1 -0
- package/dist/core/verified-run/writer-phase.js +76 -0
- package/dist/core/verified-run/writer-phase.js.map +1 -0
- package/dist/core/verified-run/writer-projection.d.ts +11 -0
- package/dist/core/verified-run/writer-projection.d.ts.map +1 -0
- package/dist/core/verified-run/writer-projection.js +70 -0
- package/dist/core/verified-run/writer-projection.js.map +1 -0
- package/dist/core/verified-run/writer-recovery.d.ts +16 -0
- package/dist/core/verified-run/writer-recovery.d.ts.map +1 -0
- package/dist/core/verified-run/writer-recovery.js +107 -0
- package/dist/core/verified-run/writer-recovery.js.map +1 -0
- package/dist/core/workload-permit-pool.d.ts +1 -3
- package/dist/core/workload-permit-pool.d.ts.map +1 -1
- package/dist/core/workload-permit-pool.js +11 -11
- package/dist/core/workload-permit-pool.js.map +1 -1
- package/dist/guardrails/evidence-system.d.ts +1 -1
- package/dist/guardrails/evidence-system.d.ts.map +1 -1
- package/dist/guardrails/evidence-system.js +18 -29
- package/dist/guardrails/evidence-system.js.map +1 -1
- package/dist/guardrails/merge-gate-result.d.ts +4 -0
- package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
- package/dist/guardrails/merge-gate-result.js +32 -0
- package/dist/guardrails/merge-gate-result.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +17 -23
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/session-failure.d.ts +13 -0
- package/dist/modes/interactive/components/session-failure.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-failure.js +81 -0
- package/dist/modes/interactive/components/session-failure.js.map +1 -0
- package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
- package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-login-options.js +54 -0
- package/dist/modes/interactive/interactive-login-options.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +8 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +183 -171
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
- package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-resume-command.js +24 -0
- package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
- package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
- package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-tool-result.js +59 -0
- package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
- package/dist/modes/interactive/tui-diagnostics.d.ts +36 -0
- package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -0
- package/dist/modes/interactive/tui-diagnostics.js +105 -0
- package/dist/modes/interactive/tui-diagnostics.js.map +1 -0
- package/dist/modes/interactive/tui-runtime-info.d.ts +20 -0
- package/dist/modes/interactive/tui-runtime-info.d.ts.map +1 -0
- package/dist/modes/interactive/tui-runtime-info.js +76 -0
- package/dist/modes/interactive/tui-runtime-info.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +22 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +10 -60
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/terminal-links.d.ts +13 -0
- package/dist/utils/terminal-links.d.ts.map +1 -0
- package/dist/utils/terminal-links.js +68 -0
- package/dist/utils/terminal-links.js.map +1 -0
- package/dist/utils/windows-clipboard-image.d.ts +16 -0
- package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
- package/dist/utils/windows-clipboard-image.js +87 -0
- package/dist/utils/windows-clipboard-image.js.map +1 -0
- package/docs/adaptorch-onboarding.md +80 -0
- package/docs/containerization.md +12 -0
- package/docs/context-files.md +97 -0
- package/docs/correctness-wall.md +8 -0
- package/docs/custom-provider.md +35 -0
- package/docs/development.md +28 -3
- package/docs/environment-variables.md +2 -0
- package/docs/grok-harness.md +4 -0
- package/docs/harness-boundaries.md +154 -0
- package/docs/harness-improvements.md +90 -0
- package/docs/json.md +19 -0
- package/docs/keybindings.md +2 -2
- package/docs/mcp.md +22 -2
- package/docs/metrics.md +66 -16
- package/docs/model-catalog-refresh.md +190 -0
- package/docs/model-contract.md +168 -0
- package/docs/models.md +21 -4
- package/docs/provider-resilience.md +5 -3
- package/docs/providers.md +68 -1
- package/docs/quickstart.md +4 -0
- package/docs/release-audit-0.98.4.md +112 -0
- package/docs/release-audit-0.98.5.md +84 -0
- package/docs/review-bundle-followup.md +195 -0
- package/docs/run-protocol.md +33 -1
- package/docs/runtime-algorithms.md +45 -0
- package/docs/sdk.md +204 -2
- package/docs/sessions.md +1 -1
- package/docs/settings.md +17 -1
- package/docs/skills.md +2 -0
- package/docs/tb21-audit.md +131 -0
- package/docs/terminal-setup.md +20 -0
- package/docs/usage.md +77 -1
- package/docs/verified-run-testing.md +417 -0
- package/docs/verified-run.md +388 -0
- package/docs/windows.md +48 -0
- package/examples/README.md +4 -0
- package/examples/context/AGENTS.md +64 -0
- package/examples/context/CLAUDE.md +17 -0
- package/examples/context/INTERNET.md +42 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +6 -6
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { chmodSync, lstatSync, mkdirSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { assertDirectory, digestBytes, digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError, } from "./storage.js";
|
|
4
|
+
function safePath(path) {
|
|
5
|
+
if (!path ||
|
|
6
|
+
/[\\\u0000-\u001f\u007f]/.test(path) ||
|
|
7
|
+
path.split("/").some((part) => ["", ".", "..", ".git", ".omk"].includes(part))) {
|
|
8
|
+
throw new VerifiedRunError("file_type");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Entire regular-file tree, including dot/untracked files; .git/.omk metadata is excluded by this profile. */
|
|
12
|
+
export function captureCandidate(root, limits) {
|
|
13
|
+
assertDirectory(root);
|
|
14
|
+
const files = [];
|
|
15
|
+
const directories = [];
|
|
16
|
+
const contents = new Map();
|
|
17
|
+
let bytesUsed = 0;
|
|
18
|
+
const visit = (prefix) => {
|
|
19
|
+
const names = readdirSync(join(root, prefix), { encoding: "buffer" })
|
|
20
|
+
.map((name) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(name))
|
|
21
|
+
.sort();
|
|
22
|
+
for (const name of names) {
|
|
23
|
+
if (!prefix && (name === ".git" || name === ".omk"))
|
|
24
|
+
continue;
|
|
25
|
+
const path = prefix ? `${prefix}/${name}` : name;
|
|
26
|
+
safePath(path);
|
|
27
|
+
if (files.length + directories.length >= limits.maxFiles)
|
|
28
|
+
throw new VerifiedRunError("storage_limit");
|
|
29
|
+
const absolute = join(root, path);
|
|
30
|
+
const stat = lstatSync(absolute);
|
|
31
|
+
if (stat.isDirectory()) {
|
|
32
|
+
if ((stat.mode & 0o7777) !== 0o755)
|
|
33
|
+
throw new VerifiedRunError("file_type");
|
|
34
|
+
directories.push(path);
|
|
35
|
+
visit(path);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!stat.isFile() || stat.nlink !== 1 || (stat.mode & 0o7000) !== 0)
|
|
39
|
+
throw new VerifiedRunError("file_type");
|
|
40
|
+
const bytes = readRegularFile(absolute, limits.maxBytes - bytesUsed);
|
|
41
|
+
bytesUsed += bytes.length;
|
|
42
|
+
const digest = digestBytes(bytes);
|
|
43
|
+
contents.set(digest, bytes);
|
|
44
|
+
files.push(Object.freeze({ path, mode: stat.mode & 0o777, digest, size: bytes.length }));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
visit("");
|
|
48
|
+
const manifest = Object.freeze({
|
|
49
|
+
version: 1,
|
|
50
|
+
directories: Object.freeze(directories),
|
|
51
|
+
files: Object.freeze(files),
|
|
52
|
+
});
|
|
53
|
+
return { manifest, digest: digestObject(manifest), contents };
|
|
54
|
+
}
|
|
55
|
+
export function materializeCandidate(snapshot, target) {
|
|
56
|
+
mkdirSync(target, { mode: 0o700 });
|
|
57
|
+
for (const directory of snapshot.manifest.directories)
|
|
58
|
+
mkdirSync(join(target, directory), { mode: 0o755 });
|
|
59
|
+
for (const file of snapshot.manifest.files) {
|
|
60
|
+
const bytes = snapshot.contents.get(file.digest);
|
|
61
|
+
if (!bytes)
|
|
62
|
+
throw new VerifiedRunError("integrity");
|
|
63
|
+
publishBytes(join(target, file.path), bytes);
|
|
64
|
+
chmodSync(join(target, file.path), file.mode);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function assertCandidateScope(base, candidate, writable) {
|
|
68
|
+
const before = new Map(base.files.map((file) => [file.path, digestObject(file)]));
|
|
69
|
+
const after = new Map(candidate.files.map((file) => [file.path, digestObject(file)]));
|
|
70
|
+
for (const directory of base.directories)
|
|
71
|
+
before.set(`${directory}/`, "directory");
|
|
72
|
+
for (const directory of candidate.directories)
|
|
73
|
+
after.set(`${directory}/`, "directory");
|
|
74
|
+
for (const path of new Set([...before.keys(), ...after.keys()])) {
|
|
75
|
+
if (before.get(path) === after.get(path))
|
|
76
|
+
continue;
|
|
77
|
+
const normalized = path.endsWith("/") ? path.slice(0, -1) : path;
|
|
78
|
+
if (!writable.some((scope) => normalized === scope || normalized.startsWith(`${scope}/`)))
|
|
79
|
+
throw new VerifiedRunError("scope_changed");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function storeCandidate(snapshot, runPath) {
|
|
83
|
+
for (const [digest, bytes] of snapshot.contents)
|
|
84
|
+
publishBytes(join(runPath, "blobs", digest), bytes);
|
|
85
|
+
publishObject(join(runPath, "candidates", `${snapshot.digest}.json`), snapshot.manifest);
|
|
86
|
+
}
|
|
87
|
+
export function loadCandidate(runPath, digest, limits) {
|
|
88
|
+
if (!/^[a-f0-9]{64}$/.test(digest))
|
|
89
|
+
throw new VerifiedRunError("integrity");
|
|
90
|
+
const raw = readJson(join(runPath, "candidates", `${digest}.json`), 4194304);
|
|
91
|
+
if (digestObject(raw) !== digest ||
|
|
92
|
+
typeof raw !== "object" ||
|
|
93
|
+
raw === null ||
|
|
94
|
+
!("version" in raw) ||
|
|
95
|
+
raw.version !== 1 ||
|
|
96
|
+
!("files" in raw) ||
|
|
97
|
+
!Array.isArray(raw.files) ||
|
|
98
|
+
!("directories" in raw) ||
|
|
99
|
+
!Array.isArray(raw.directories)) {
|
|
100
|
+
throw new VerifiedRunError("integrity");
|
|
101
|
+
}
|
|
102
|
+
if (raw.files.length + raw.directories.length > limits.maxFiles)
|
|
103
|
+
throw new VerifiedRunError("integrity");
|
|
104
|
+
const files = [];
|
|
105
|
+
const directories = [];
|
|
106
|
+
const paths = new Set();
|
|
107
|
+
let total = 0;
|
|
108
|
+
for (const directory of raw.directories) {
|
|
109
|
+
if (typeof directory !== "string")
|
|
110
|
+
throw new VerifiedRunError("integrity");
|
|
111
|
+
safePath(directory);
|
|
112
|
+
if (paths.has(directory))
|
|
113
|
+
throw new VerifiedRunError("integrity");
|
|
114
|
+
paths.add(directory);
|
|
115
|
+
directories.push(directory);
|
|
116
|
+
}
|
|
117
|
+
const contents = new Map();
|
|
118
|
+
const rawFiles = raw.files;
|
|
119
|
+
for (const file of rawFiles) {
|
|
120
|
+
if (typeof file !== "object" ||
|
|
121
|
+
file === null ||
|
|
122
|
+
!("path" in file) ||
|
|
123
|
+
typeof file.path !== "string" ||
|
|
124
|
+
!("digest" in file) ||
|
|
125
|
+
typeof file.digest !== "string" ||
|
|
126
|
+
!/^[a-f0-9]{64}$/.test(file.digest) ||
|
|
127
|
+
!("mode" in file) ||
|
|
128
|
+
typeof file.mode !== "number" ||
|
|
129
|
+
!Number.isSafeInteger(file.mode) ||
|
|
130
|
+
file.mode < 0 ||
|
|
131
|
+
file.mode > 0o777 ||
|
|
132
|
+
!("size" in file) ||
|
|
133
|
+
typeof file.size !== "number" ||
|
|
134
|
+
!Number.isSafeInteger(file.size) ||
|
|
135
|
+
file.size < 0)
|
|
136
|
+
throw new VerifiedRunError("integrity");
|
|
137
|
+
safePath(file.path);
|
|
138
|
+
if (paths.has(file.path))
|
|
139
|
+
throw new VerifiedRunError("integrity");
|
|
140
|
+
paths.add(file.path);
|
|
141
|
+
total += file.size;
|
|
142
|
+
if (total > limits.maxBytes)
|
|
143
|
+
throw new VerifiedRunError("integrity");
|
|
144
|
+
let bytes;
|
|
145
|
+
try {
|
|
146
|
+
bytes = readRegularFile(join(runPath, "blobs", file.digest), file.size);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error instanceof Error)
|
|
150
|
+
throw new VerifiedRunError("integrity");
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
if (bytes.length !== file.size || digestBytes(bytes) !== file.digest)
|
|
154
|
+
throw new VerifiedRunError("integrity");
|
|
155
|
+
contents.set(file.digest, bytes);
|
|
156
|
+
files.push(Object.freeze({ path: file.path, mode: file.mode, digest: file.digest, size: file.size }));
|
|
157
|
+
}
|
|
158
|
+
const manifest = Object.freeze({
|
|
159
|
+
version: 1,
|
|
160
|
+
directories: Object.freeze(directories),
|
|
161
|
+
files: Object.freeze(files),
|
|
162
|
+
});
|
|
163
|
+
if (digestObject(manifest) !== digest)
|
|
164
|
+
throw new VerifiedRunError("integrity");
|
|
165
|
+
return { manifest, digest, contents };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=candidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate.js","sourceRoot":"","sources":["../../../src/core/verified-run/candidate.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, lstatSync, mkdirSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { RunPhaseBudget } from \"omk-protocol\";\nimport {\n\tassertDirectory,\n\tdigestBytes,\n\tdigestObject,\n\tpublishBytes,\n\tpublishObject,\n\treadJson,\n\treadRegularFile,\n\tVerifiedRunError,\n} from \"./storage.ts\";\n\nexport interface CandidateFile {\n\treadonly path: string;\n\treadonly mode: number;\n\treadonly digest: string;\n\treadonly size: number;\n}\nexport interface CandidateManifest {\n\treadonly version: 1;\n\treadonly directories: readonly string[];\n\treadonly files: readonly CandidateFile[];\n}\nexport interface CandidateSnapshot {\n\treadonly manifest: CandidateManifest;\n\treadonly digest: string;\n\treadonly contents: ReadonlyMap<string, Buffer>;\n}\n\nfunction safePath(path: string): void {\n\tif (\n\t\t!path ||\n\t\t/[\\\\\\u0000-\\u001f\\u007f]/.test(path) ||\n\t\tpath.split(\"/\").some((part) => [\"\", \".\", \"..\", \".git\", \".omk\"].includes(part))\n\t) {\n\t\tthrow new VerifiedRunError(\"file_type\");\n\t}\n}\n\n/** Entire regular-file tree, including dot/untracked files; .git/.omk metadata is excluded by this profile. */\nexport function captureCandidate(root: string, limits: RunPhaseBudget): CandidateSnapshot {\n\tassertDirectory(root);\n\tconst files: CandidateFile[] = [];\n\tconst directories: string[] = [];\n\tconst contents = new Map<string, Buffer>();\n\tlet bytesUsed = 0;\n\tconst visit = (prefix: string): void => {\n\t\tconst names = readdirSync(join(root, prefix), { encoding: \"buffer\" })\n\t\t\t.map((name) => new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(name))\n\t\t\t.sort();\n\t\tfor (const name of names) {\n\t\t\tif (!prefix && (name === \".git\" || name === \".omk\")) continue;\n\t\t\tconst path = prefix ? `${prefix}/${name}` : name;\n\t\t\tsafePath(path);\n\t\t\tif (files.length + directories.length >= limits.maxFiles) throw new VerifiedRunError(\"storage_limit\");\n\t\t\tconst absolute = join(root, path);\n\t\t\tconst stat = lstatSync(absolute);\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\tif ((stat.mode & 0o7777) !== 0o755) throw new VerifiedRunError(\"file_type\");\n\t\t\t\tdirectories.push(path);\n\t\t\t\tvisit(path);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!stat.isFile() || stat.nlink !== 1 || (stat.mode & 0o7000) !== 0) throw new VerifiedRunError(\"file_type\");\n\t\t\tconst bytes = readRegularFile(absolute, limits.maxBytes - bytesUsed);\n\t\t\tbytesUsed += bytes.length;\n\t\t\tconst digest = digestBytes(bytes);\n\t\t\tcontents.set(digest, bytes);\n\t\t\tfiles.push(Object.freeze({ path, mode: stat.mode & 0o777, digest, size: bytes.length }));\n\t\t}\n\t};\n\tvisit(\"\");\n\tconst manifest: CandidateManifest = Object.freeze({\n\t\tversion: 1,\n\t\tdirectories: Object.freeze(directories),\n\t\tfiles: Object.freeze(files),\n\t});\n\treturn { manifest, digest: digestObject(manifest), contents };\n}\n\nexport function materializeCandidate(snapshot: CandidateSnapshot, target: string): void {\n\tmkdirSync(target, { mode: 0o700 });\n\tfor (const directory of snapshot.manifest.directories) mkdirSync(join(target, directory), { mode: 0o755 });\n\tfor (const file of snapshot.manifest.files) {\n\t\tconst bytes = snapshot.contents.get(file.digest);\n\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\tpublishBytes(join(target, file.path), bytes);\n\t\tchmodSync(join(target, file.path), file.mode);\n\t}\n}\n\nexport function assertCandidateScope(\n\tbase: CandidateManifest,\n\tcandidate: CandidateManifest,\n\twritable: readonly string[],\n): void {\n\tconst before = new Map(base.files.map((file) => [file.path, digestObject(file)]));\n\tconst after = new Map(candidate.files.map((file) => [file.path, digestObject(file)]));\n\tfor (const directory of base.directories) before.set(`${directory}/`, \"directory\");\n\tfor (const directory of candidate.directories) after.set(`${directory}/`, \"directory\");\n\tfor (const path of new Set([...before.keys(), ...after.keys()])) {\n\t\tif (before.get(path) === after.get(path)) continue;\n\t\tconst normalized = path.endsWith(\"/\") ? path.slice(0, -1) : path;\n\t\tif (!writable.some((scope) => normalized === scope || normalized.startsWith(`${scope}/`)))\n\t\t\tthrow new VerifiedRunError(\"scope_changed\");\n\t}\n}\n\nexport function storeCandidate(snapshot: CandidateSnapshot, runPath: string): void {\n\tfor (const [digest, bytes] of snapshot.contents) publishBytes(join(runPath, \"blobs\", digest), bytes);\n\tpublishObject(join(runPath, \"candidates\", `${snapshot.digest}.json`), snapshot.manifest);\n}\n\nexport function loadCandidate(runPath: string, digest: string, limits: RunPhaseBudget): CandidateSnapshot {\n\tif (!/^[a-f0-9]{64}$/.test(digest)) throw new VerifiedRunError(\"integrity\");\n\tconst raw = readJson(join(runPath, \"candidates\", `${digest}.json`), 4194304);\n\tif (\n\t\tdigestObject(raw) !== digest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"version\" in raw) ||\n\t\traw.version !== 1 ||\n\t\t!(\"files\" in raw) ||\n\t\t!Array.isArray(raw.files) ||\n\t\t!(\"directories\" in raw) ||\n\t\t!Array.isArray(raw.directories)\n\t) {\n\t\tthrow new VerifiedRunError(\"integrity\");\n\t}\n\tif (raw.files.length + raw.directories.length > limits.maxFiles) throw new VerifiedRunError(\"integrity\");\n\tconst files: CandidateFile[] = [];\n\tconst directories: string[] = [];\n\tconst paths = new Set<string>();\n\tlet total = 0;\n\tfor (const directory of raw.directories) {\n\t\tif (typeof directory !== \"string\") throw new VerifiedRunError(\"integrity\");\n\t\tsafePath(directory);\n\t\tif (paths.has(directory)) throw new VerifiedRunError(\"integrity\");\n\t\tpaths.add(directory);\n\t\tdirectories.push(directory);\n\t}\n\tconst contents = new Map<string, Buffer>();\n\tconst rawFiles: readonly unknown[] = raw.files;\n\tfor (const file of rawFiles) {\n\t\tif (\n\t\t\ttypeof file !== \"object\" ||\n\t\t\tfile === null ||\n\t\t\t!(\"path\" in file) ||\n\t\t\ttypeof file.path !== \"string\" ||\n\t\t\t!(\"digest\" in file) ||\n\t\t\ttypeof file.digest !== \"string\" ||\n\t\t\t!/^[a-f0-9]{64}$/.test(file.digest) ||\n\t\t\t!(\"mode\" in file) ||\n\t\t\ttypeof file.mode !== \"number\" ||\n\t\t\t!Number.isSafeInteger(file.mode) ||\n\t\t\tfile.mode < 0 ||\n\t\t\tfile.mode > 0o777 ||\n\t\t\t!(\"size\" in file) ||\n\t\t\ttypeof file.size !== \"number\" ||\n\t\t\t!Number.isSafeInteger(file.size) ||\n\t\t\tfile.size < 0\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\tsafePath(file.path);\n\t\tif (paths.has(file.path)) throw new VerifiedRunError(\"integrity\");\n\t\tpaths.add(file.path);\n\t\ttotal += file.size;\n\t\tif (total > limits.maxBytes) throw new VerifiedRunError(\"integrity\");\n\t\tlet bytes: Buffer;\n\t\ttry {\n\t\t\tbytes = readRegularFile(join(runPath, \"blobs\", file.digest), file.size);\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) throw new VerifiedRunError(\"integrity\");\n\t\t\tthrow error;\n\t\t}\n\t\tif (bytes.length !== file.size || digestBytes(bytes) !== file.digest) throw new VerifiedRunError(\"integrity\");\n\t\tcontents.set(file.digest, bytes);\n\t\tfiles.push(Object.freeze({ path: file.path, mode: file.mode, digest: file.digest, size: file.size }));\n\t}\n\tconst manifest: CandidateManifest = Object.freeze({\n\t\tversion: 1,\n\t\tdirectories: Object.freeze(directories),\n\t\tfiles: Object.freeze(files),\n\t});\n\tif (digestObject(manifest) !== digest) throw new VerifiedRunError(\"integrity\");\n\treturn { manifest, digest, contents };\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RunCheck, RunContract } from "omk-protocol";
|
|
2
|
+
import type { EvidenceReceipt } from "../../types/evidence.ts";
|
|
3
|
+
import type { SandboxOutcome } from "./broker.ts";
|
|
4
|
+
import type { CandidateManifest } from "./candidate.ts";
|
|
5
|
+
import type { CheckObservation } from "./evidence-binding.ts";
|
|
6
|
+
export declare function preflightCheckReceipts(contract: RunContract): void;
|
|
7
|
+
export declare function storeCheckReceipt(runPath: string, contract: RunContract, execution: {
|
|
8
|
+
readonly check: RunCheck;
|
|
9
|
+
readonly executionId: string;
|
|
10
|
+
readonly result: SandboxOutcome;
|
|
11
|
+
readonly timeoutMs: number;
|
|
12
|
+
readonly manifest: CandidateManifest;
|
|
13
|
+
}): string;
|
|
14
|
+
export declare function readCheckReceipts(runPath: string, contract: RunContract, binding: {
|
|
15
|
+
readonly manifest: CandidateManifest;
|
|
16
|
+
readonly checks: readonly CheckObservation[];
|
|
17
|
+
}): readonly EvidenceReceipt[];
|
|
18
|
+
//# sourceMappingURL=check-receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-receipt.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/check-receipt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,KAAK,EAEX,eAAe,EAGf,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAS9D,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAElE;AAuBD,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE;IACV,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;CACrC,GACC,MAAM,CA0BR;AAED,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE;IACR,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC7C,GACC,SAAS,eAAe,EAAE,CA+B5B","sourcesContent":["import { join } from \"node:path\";\nimport type { RunCheck, RunContract } from \"omk-protocol\";\nimport { assertCredentialFreeEvidenceCommand } from \"../../guardrails/command-redaction.ts\";\nimport { createEvidenceReceipt, parseSha256Hex, validateEvidenceReceipt } from \"../../guardrails/evidence-receipt.ts\";\nimport { computeWorkspaceManifestSha256 } from \"../../guardrails/workspace-fingerprint.ts\";\nimport type {\n\tEvidenceCommandDescriptor,\n\tEvidenceReceipt,\n\tEvidenceReceiptDisposition,\n\tWorkspaceFingerprint,\n} from \"../../types/evidence.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport type { SandboxOutcome } from \"./broker.ts\";\nimport type { CandidateManifest } from \"./candidate.ts\";\nimport type { CheckObservation } from \"./evidence-binding.ts\";\nimport { publishObject, readJson, VerifiedRunError } from \"./storage.ts\";\n\nfunction command(check: RunCheck): EvidenceCommandDescriptor {\n\tconst executable = check.argv[0];\n\tif (!executable) throw new VerifiedRunError(\"integrity\");\n\treturn { kind: \"argv\", executable, argv: check.argv.slice(1) };\n}\n\nexport function preflightCheckReceipts(contract: RunContract): void {\n\tfor (const check of contract.checks) assertCredentialFreeEvidenceCommand(command(check));\n}\n\nfunction fingerprint(manifest: CandidateManifest): WorkspaceFingerprint {\n\tconst files = [...manifest.files].sort((left, right) =>\n\t\tleft.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n\t);\n\tconst scope = { root: \"/workspace\", artifactPaths: files.map((file) => file.path) };\n\tconst artifacts = files.map((file) => ({\n\t\tpath: file.path,\n\t\tstate: \"file\" as const,\n\t\tsha256: parseSha256Hex(file.digest),\n\t\tsize: file.size,\n\t}));\n\treturn { kind: \"artifact-set\", scope, artifacts, manifestSha256: computeWorkspaceManifestSha256(scope, artifacts) };\n}\n\nfunction disposition(result: Pick<SandboxOutcome, \"failure\" | \"exitCode\">): EvidenceReceiptDisposition {\n\tif (result.failure === \"deadline\") return { status: \"timeout\", exitCode: null };\n\tif (result.failure === \"cancelled\" || result.failure === \"output_limit\" || result.exitCode === null)\n\t\treturn { status: \"aborted\", exitCode: null };\n\treturn result.exitCode === 0 ? { status: \"passed\", exitCode: 0 } : { status: \"failed\", exitCode: result.exitCode };\n}\n\nexport function storeCheckReceipt(\n\trunPath: string,\n\tcontract: RunContract,\n\texecution: {\n\t\treadonly check: RunCheck;\n\t\treadonly executionId: string;\n\t\treadonly result: SandboxOutcome;\n\t\treadonly timeoutMs: number;\n\t\treadonly manifest: CandidateManifest;\n\t},\n): string {\n\tconst workspace = fingerprint(execution.manifest);\n\tconst result = execution.result;\n\tconst receipt = createEvidenceReceipt({\n\t\treceiptId: execution.executionId,\n\t\tgoalId: contract.runId,\n\t\tclaim: `Exact stdout for ${execution.check.claimId}`,\n\t\tcommand: command(execution.check),\n\t\tcwd: \"/workspace\",\n\t\ttimeoutMs: execution.timeoutMs,\n\t\tstartedAt: result.startedAt,\n\t\tfinishedAt: result.finishedAt,\n\t\tdurationMs: Date.parse(result.finishedAt) - Date.parse(result.startedAt),\n\t\tworkspaceBefore: workspace,\n\t\tworkspaceAfter: workspace,\n\t\texecutor: \"internal\",\n\t\ttoolCallId: execution.executionId,\n\t\talreadyRedactedOutput: {\n\t\t\tredactionPolicyId: \"omk-verified-run-v1+forced-text+prefix-32k-per-stream\",\n\t\t\tstdout: Buffer.from(redactSensitiveTextForced(result.stdout.toString(\"utf8\"))).subarray(0, 32768),\n\t\t\tstderr: Buffer.from(redactSensitiveTextForced(result.stderr.toString(\"utf8\"))).subarray(0, 32768),\n\t\t},\n\t\t...disposition(result),\n\t});\n\tpublishObject(join(runPath, \"receipts\", `${receipt.envelope.coreSha256}.json`), receipt);\n\treturn receipt.envelope.coreSha256;\n}\n\nexport function readCheckReceipts(\n\trunPath: string,\n\tcontract: RunContract,\n\tbinding: {\n\t\treadonly manifest: CandidateManifest;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): readonly EvidenceReceipt[] {\n\tconst workspace = fingerprint(binding.manifest);\n\treturn Object.freeze(\n\t\tbinding.checks.map((observation) => {\n\t\t\tconst digest = observation.receiptCoreDigest;\n\t\t\tif (!digest || !/^[a-f0-9]{64}$/.test(digest)) throw new VerifiedRunError(\"integrity\");\n\t\t\tconst receipt = validateEvidenceReceipt(readJson(join(runPath, \"receipts\", `${digest}.json`), 8388608));\n\t\t\tconst core = receipt.core;\n\t\t\tconst check = contract.checks.find((item) => item.claimId === observation.claimId);\n\t\t\tconst expected = disposition(observation);\n\t\t\tif (\n\t\t\t\t!check ||\n\t\t\t\tcanonicalJson(receipt.envelope) !== canonicalJson({ coreSha256: digest }) ||\n\t\t\t\tcore.receiptId !== observation.executionId ||\n\t\t\t\tcore.toolCallId !== observation.executionId ||\n\t\t\t\tcore.goalId !== contract.runId ||\n\t\t\t\tcore.executor !== \"internal\" ||\n\t\t\t\tcore.claim !== `Exact stdout for ${check.claimId}` ||\n\t\t\t\tcore.cwd !== \"/workspace\" ||\n\t\t\t\tcore.status !== expected.status ||\n\t\t\t\tcore.exitCode !== expected.exitCode ||\n\t\t\t\tcore.timeoutMs === null ||\n\t\t\t\tcore.timeoutMs > contract.budget.verifyMs ||\n\t\t\t\tcanonicalJson(core.command) !== canonicalJson(command(check)) ||\n\t\t\t\tcanonicalJson(core.workspaceBefore) !== canonicalJson(workspace) ||\n\t\t\t\tcanonicalJson(core.workspaceAfter) !== canonicalJson(workspace)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\treturn receipt;\n\t\t}),\n\t);\n}\n"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { assertCredentialFreeEvidenceCommand } from "../../guardrails/command-redaction.js";
|
|
3
|
+
import { createEvidenceReceipt, parseSha256Hex, validateEvidenceReceipt } from "../../guardrails/evidence-receipt.js";
|
|
4
|
+
import { computeWorkspaceManifestSha256 } from "../../guardrails/workspace-fingerprint.js";
|
|
5
|
+
import { redactSensitiveTextForced } from "../redaction.js";
|
|
6
|
+
import { canonicalJson } from "../run-journal.js";
|
|
7
|
+
import { publishObject, readJson, VerifiedRunError } from "./storage.js";
|
|
8
|
+
function command(check) {
|
|
9
|
+
const executable = check.argv[0];
|
|
10
|
+
if (!executable)
|
|
11
|
+
throw new VerifiedRunError("integrity");
|
|
12
|
+
return { kind: "argv", executable, argv: check.argv.slice(1) };
|
|
13
|
+
}
|
|
14
|
+
export function preflightCheckReceipts(contract) {
|
|
15
|
+
for (const check of contract.checks)
|
|
16
|
+
assertCredentialFreeEvidenceCommand(command(check));
|
|
17
|
+
}
|
|
18
|
+
function fingerprint(manifest) {
|
|
19
|
+
const files = [...manifest.files].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
|
|
20
|
+
const scope = { root: "/workspace", artifactPaths: files.map((file) => file.path) };
|
|
21
|
+
const artifacts = files.map((file) => ({
|
|
22
|
+
path: file.path,
|
|
23
|
+
state: "file",
|
|
24
|
+
sha256: parseSha256Hex(file.digest),
|
|
25
|
+
size: file.size,
|
|
26
|
+
}));
|
|
27
|
+
return { kind: "artifact-set", scope, artifacts, manifestSha256: computeWorkspaceManifestSha256(scope, artifacts) };
|
|
28
|
+
}
|
|
29
|
+
function disposition(result) {
|
|
30
|
+
if (result.failure === "deadline")
|
|
31
|
+
return { status: "timeout", exitCode: null };
|
|
32
|
+
if (result.failure === "cancelled" || result.failure === "output_limit" || result.exitCode === null)
|
|
33
|
+
return { status: "aborted", exitCode: null };
|
|
34
|
+
return result.exitCode === 0 ? { status: "passed", exitCode: 0 } : { status: "failed", exitCode: result.exitCode };
|
|
35
|
+
}
|
|
36
|
+
export function storeCheckReceipt(runPath, contract, execution) {
|
|
37
|
+
const workspace = fingerprint(execution.manifest);
|
|
38
|
+
const result = execution.result;
|
|
39
|
+
const receipt = createEvidenceReceipt({
|
|
40
|
+
receiptId: execution.executionId,
|
|
41
|
+
goalId: contract.runId,
|
|
42
|
+
claim: `Exact stdout for ${execution.check.claimId}`,
|
|
43
|
+
command: command(execution.check),
|
|
44
|
+
cwd: "/workspace",
|
|
45
|
+
timeoutMs: execution.timeoutMs,
|
|
46
|
+
startedAt: result.startedAt,
|
|
47
|
+
finishedAt: result.finishedAt,
|
|
48
|
+
durationMs: Date.parse(result.finishedAt) - Date.parse(result.startedAt),
|
|
49
|
+
workspaceBefore: workspace,
|
|
50
|
+
workspaceAfter: workspace,
|
|
51
|
+
executor: "internal",
|
|
52
|
+
toolCallId: execution.executionId,
|
|
53
|
+
alreadyRedactedOutput: {
|
|
54
|
+
redactionPolicyId: "omk-verified-run-v1+forced-text+prefix-32k-per-stream",
|
|
55
|
+
stdout: Buffer.from(redactSensitiveTextForced(result.stdout.toString("utf8"))).subarray(0, 32768),
|
|
56
|
+
stderr: Buffer.from(redactSensitiveTextForced(result.stderr.toString("utf8"))).subarray(0, 32768),
|
|
57
|
+
},
|
|
58
|
+
...disposition(result),
|
|
59
|
+
});
|
|
60
|
+
publishObject(join(runPath, "receipts", `${receipt.envelope.coreSha256}.json`), receipt);
|
|
61
|
+
return receipt.envelope.coreSha256;
|
|
62
|
+
}
|
|
63
|
+
export function readCheckReceipts(runPath, contract, binding) {
|
|
64
|
+
const workspace = fingerprint(binding.manifest);
|
|
65
|
+
return Object.freeze(binding.checks.map((observation) => {
|
|
66
|
+
const digest = observation.receiptCoreDigest;
|
|
67
|
+
if (!digest || !/^[a-f0-9]{64}$/.test(digest))
|
|
68
|
+
throw new VerifiedRunError("integrity");
|
|
69
|
+
const receipt = validateEvidenceReceipt(readJson(join(runPath, "receipts", `${digest}.json`), 8388608));
|
|
70
|
+
const core = receipt.core;
|
|
71
|
+
const check = contract.checks.find((item) => item.claimId === observation.claimId);
|
|
72
|
+
const expected = disposition(observation);
|
|
73
|
+
if (!check ||
|
|
74
|
+
canonicalJson(receipt.envelope) !== canonicalJson({ coreSha256: digest }) ||
|
|
75
|
+
core.receiptId !== observation.executionId ||
|
|
76
|
+
core.toolCallId !== observation.executionId ||
|
|
77
|
+
core.goalId !== contract.runId ||
|
|
78
|
+
core.executor !== "internal" ||
|
|
79
|
+
core.claim !== `Exact stdout for ${check.claimId}` ||
|
|
80
|
+
core.cwd !== "/workspace" ||
|
|
81
|
+
core.status !== expected.status ||
|
|
82
|
+
core.exitCode !== expected.exitCode ||
|
|
83
|
+
core.timeoutMs === null ||
|
|
84
|
+
core.timeoutMs > contract.budget.verifyMs ||
|
|
85
|
+
canonicalJson(core.command) !== canonicalJson(command(check)) ||
|
|
86
|
+
canonicalJson(core.workspaceBefore) !== canonicalJson(workspace) ||
|
|
87
|
+
canonicalJson(core.workspaceAfter) !== canonicalJson(workspace))
|
|
88
|
+
throw new VerifiedRunError("integrity");
|
|
89
|
+
return receipt;
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=check-receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-receipt.js","sourceRoot":"","sources":["../../../src/core/verified-run/check-receipt.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { RunCheck, RunContract } from \"omk-protocol\";\nimport { assertCredentialFreeEvidenceCommand } from \"../../guardrails/command-redaction.ts\";\nimport { createEvidenceReceipt, parseSha256Hex, validateEvidenceReceipt } from \"../../guardrails/evidence-receipt.ts\";\nimport { computeWorkspaceManifestSha256 } from \"../../guardrails/workspace-fingerprint.ts\";\nimport type {\n\tEvidenceCommandDescriptor,\n\tEvidenceReceipt,\n\tEvidenceReceiptDisposition,\n\tWorkspaceFingerprint,\n} from \"../../types/evidence.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport type { SandboxOutcome } from \"./broker.ts\";\nimport type { CandidateManifest } from \"./candidate.ts\";\nimport type { CheckObservation } from \"./evidence-binding.ts\";\nimport { publishObject, readJson, VerifiedRunError } from \"./storage.ts\";\n\nfunction command(check: RunCheck): EvidenceCommandDescriptor {\n\tconst executable = check.argv[0];\n\tif (!executable) throw new VerifiedRunError(\"integrity\");\n\treturn { kind: \"argv\", executable, argv: check.argv.slice(1) };\n}\n\nexport function preflightCheckReceipts(contract: RunContract): void {\n\tfor (const check of contract.checks) assertCredentialFreeEvidenceCommand(command(check));\n}\n\nfunction fingerprint(manifest: CandidateManifest): WorkspaceFingerprint {\n\tconst files = [...manifest.files].sort((left, right) =>\n\t\tleft.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n\t);\n\tconst scope = { root: \"/workspace\", artifactPaths: files.map((file) => file.path) };\n\tconst artifacts = files.map((file) => ({\n\t\tpath: file.path,\n\t\tstate: \"file\" as const,\n\t\tsha256: parseSha256Hex(file.digest),\n\t\tsize: file.size,\n\t}));\n\treturn { kind: \"artifact-set\", scope, artifacts, manifestSha256: computeWorkspaceManifestSha256(scope, artifacts) };\n}\n\nfunction disposition(result: Pick<SandboxOutcome, \"failure\" | \"exitCode\">): EvidenceReceiptDisposition {\n\tif (result.failure === \"deadline\") return { status: \"timeout\", exitCode: null };\n\tif (result.failure === \"cancelled\" || result.failure === \"output_limit\" || result.exitCode === null)\n\t\treturn { status: \"aborted\", exitCode: null };\n\treturn result.exitCode === 0 ? { status: \"passed\", exitCode: 0 } : { status: \"failed\", exitCode: result.exitCode };\n}\n\nexport function storeCheckReceipt(\n\trunPath: string,\n\tcontract: RunContract,\n\texecution: {\n\t\treadonly check: RunCheck;\n\t\treadonly executionId: string;\n\t\treadonly result: SandboxOutcome;\n\t\treadonly timeoutMs: number;\n\t\treadonly manifest: CandidateManifest;\n\t},\n): string {\n\tconst workspace = fingerprint(execution.manifest);\n\tconst result = execution.result;\n\tconst receipt = createEvidenceReceipt({\n\t\treceiptId: execution.executionId,\n\t\tgoalId: contract.runId,\n\t\tclaim: `Exact stdout for ${execution.check.claimId}`,\n\t\tcommand: command(execution.check),\n\t\tcwd: \"/workspace\",\n\t\ttimeoutMs: execution.timeoutMs,\n\t\tstartedAt: result.startedAt,\n\t\tfinishedAt: result.finishedAt,\n\t\tdurationMs: Date.parse(result.finishedAt) - Date.parse(result.startedAt),\n\t\tworkspaceBefore: workspace,\n\t\tworkspaceAfter: workspace,\n\t\texecutor: \"internal\",\n\t\ttoolCallId: execution.executionId,\n\t\talreadyRedactedOutput: {\n\t\t\tredactionPolicyId: \"omk-verified-run-v1+forced-text+prefix-32k-per-stream\",\n\t\t\tstdout: Buffer.from(redactSensitiveTextForced(result.stdout.toString(\"utf8\"))).subarray(0, 32768),\n\t\t\tstderr: Buffer.from(redactSensitiveTextForced(result.stderr.toString(\"utf8\"))).subarray(0, 32768),\n\t\t},\n\t\t...disposition(result),\n\t});\n\tpublishObject(join(runPath, \"receipts\", `${receipt.envelope.coreSha256}.json`), receipt);\n\treturn receipt.envelope.coreSha256;\n}\n\nexport function readCheckReceipts(\n\trunPath: string,\n\tcontract: RunContract,\n\tbinding: {\n\t\treadonly manifest: CandidateManifest;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): readonly EvidenceReceipt[] {\n\tconst workspace = fingerprint(binding.manifest);\n\treturn Object.freeze(\n\t\tbinding.checks.map((observation) => {\n\t\t\tconst digest = observation.receiptCoreDigest;\n\t\t\tif (!digest || !/^[a-f0-9]{64}$/.test(digest)) throw new VerifiedRunError(\"integrity\");\n\t\t\tconst receipt = validateEvidenceReceipt(readJson(join(runPath, \"receipts\", `${digest}.json`), 8388608));\n\t\t\tconst core = receipt.core;\n\t\t\tconst check = contract.checks.find((item) => item.claimId === observation.claimId);\n\t\t\tconst expected = disposition(observation);\n\t\t\tif (\n\t\t\t\t!check ||\n\t\t\t\tcanonicalJson(receipt.envelope) !== canonicalJson({ coreSha256: digest }) ||\n\t\t\t\tcore.receiptId !== observation.executionId ||\n\t\t\t\tcore.toolCallId !== observation.executionId ||\n\t\t\t\tcore.goalId !== contract.runId ||\n\t\t\t\tcore.executor !== \"internal\" ||\n\t\t\t\tcore.claim !== `Exact stdout for ${check.claimId}` ||\n\t\t\t\tcore.cwd !== \"/workspace\" ||\n\t\t\t\tcore.status !== expected.status ||\n\t\t\t\tcore.exitCode !== expected.exitCode ||\n\t\t\t\tcore.timeoutMs === null ||\n\t\t\t\tcore.timeoutMs > contract.budget.verifyMs ||\n\t\t\t\tcanonicalJson(core.command) !== canonicalJson(command(check)) ||\n\t\t\t\tcanonicalJson(core.workspaceBefore) !== canonicalJson(workspace) ||\n\t\t\t\tcanonicalJson(core.workspaceAfter) !== canonicalJson(workspace)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\treturn receipt;\n\t\t}),\n\t);\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type RunContract } from "omk-protocol";
|
|
2
|
+
import { type TaskRecoveryInspection } from "./dag-recovery.ts";
|
|
3
|
+
import { type VerifiedRunEvidence } from "./evidence.ts";
|
|
4
|
+
import { type RecoveryInspection } from "./recovery.ts";
|
|
5
|
+
import type { RunProjection } from "./run-types.ts";
|
|
6
|
+
import type { VerifiedRunRuntime } from "./session-port.ts";
|
|
7
|
+
import { type WriterRecoveryInspection } from "./writer-recovery.ts";
|
|
8
|
+
export interface VerifiedRunApproval {
|
|
9
|
+
/** Trusted host grant, not a JSON field in the model-authored contract or command. */
|
|
10
|
+
readonly approvedContractDigest: string;
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
export interface VerifiedRunPlan {
|
|
14
|
+
readonly profile: RunContract["profile"];
|
|
15
|
+
readonly contractDigest: string;
|
|
16
|
+
readonly baseDigest: string;
|
|
17
|
+
readonly baseMatches: boolean;
|
|
18
|
+
readonly environmentDigest: string;
|
|
19
|
+
readonly checks: readonly string[];
|
|
20
|
+
readonly executionRequested: false;
|
|
21
|
+
}
|
|
22
|
+
export declare function planVerifiedRun(input: unknown): VerifiedRunPlan;
|
|
23
|
+
/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */
|
|
24
|
+
export declare class RunCoordinator {
|
|
25
|
+
private readonly stateRoot;
|
|
26
|
+
private readonly runtime;
|
|
27
|
+
constructor(stateRoot: string, runtime?: VerifiedRunRuntime);
|
|
28
|
+
inspect(runId: string): RunProjection;
|
|
29
|
+
inspectRecovery(runId: string): RecoveryInspection;
|
|
30
|
+
inspectWriterRecovery(runId: string): WriterRecoveryInspection;
|
|
31
|
+
inspectTaskRecovery(runId: string): TaskRecoveryInspection;
|
|
32
|
+
retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
33
|
+
evidence(runId: string): VerifiedRunEvidence;
|
|
34
|
+
artifact(runId: string, candidateDigest: string, path: string): Buffer;
|
|
35
|
+
resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
36
|
+
restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
37
|
+
start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,cAAc,CAAC;AAMtB,OAAO,EAAsC,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EAAoC,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG3F,OAAO,EAAsB,KAAK,kBAAkB,EAAyB,MAAM,eAAe,CAAC;AAEnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAY5D,OAAO,EAAgD,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEnH,MAAM,WAAW,mBAAmB;IACnC,sFAAsF;IACtF,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AACD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAY/D;AAED,qGAAqG;AACrG,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,YAAY,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAG1D;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAKpC;IAED,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAKjD;IAED,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,CAK7D;IAED,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAKzD;IAEK,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAKtF;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAW3C;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CASrE;IAEK,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAKlF;IAEK,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAQzF;IAEK,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkEnG;CACD","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n\ttype RunContract,\n} from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { acquireSessionOwnerLeaseSync } from \"../session-owner-lease.ts\";\nimport { commandEnvironmentDigest, probeVerifiedSandbox } from \"./broker.ts\";\nimport { captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { inspectTaskRecovery, retryDagTasks, type TaskRecoveryInspection } from \"./dag-recovery.ts\";\nimport { createRunIssuer, readRunEvidence, type VerifiedRunEvidence } from \"./evidence.ts\";\nimport { journalPath, readRunJournal, VerifiedRunJournal } from \"./journal.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { inspectRunRecovery, type RecoveryInspection, resumeFrozenCandidate } from \"./recovery.ts\";\nimport { anchorRunBudget, readRunClock } from \"./recovery-clock.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport type { VerifiedRunRuntime } from \"./session-port.ts\";\nimport {\n\tassertStateOutsideWorkspace,\n\tdigestBytes,\n\tdigestObject,\n\treadRegularFile,\n\tstateRunPath,\n\tVerifiedRunError,\n} from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\nimport { executeWriter } from \"./writer-phase.ts\";\nimport { inspectWriterRecovery, restartIsolatedWriter, type WriterRecoveryInspection } from \"./writer-recovery.ts\";\n\nexport interface VerifiedRunApproval {\n\t/** Trusted host grant, not a JSON field in the model-authored contract or command. */\n\treadonly approvedContractDigest: string;\n\treadonly signal?: AbortSignal;\n}\nexport interface VerifiedRunPlan {\n\treadonly profile: RunContract[\"profile\"];\n\treadonly contractDigest: string;\n\treadonly baseDigest: string;\n\treadonly baseMatches: boolean;\n\treadonly environmentDigest: string;\n\treadonly checks: readonly string[];\n\treadonly executionRequested: false;\n}\n\nexport function planVerifiedRun(input: unknown): VerifiedRunPlan {\n\tconst contract = parseRunContract(input);\n\tconst snapshot = captureCandidate(contract.workspace.root, contract.budget);\n\treturn Object.freeze({\n\t\tprofile: contract.profile,\n\t\tcontractDigest: digestObject(contract),\n\t\tbaseDigest: snapshot.digest,\n\t\tbaseMatches: snapshot.digest === contract.workspace.baseDigest,\n\t\tenvironmentDigest: commandEnvironmentDigest(contract, \"gated-v1\"),\n\t\tchecks: Object.freeze(contract.checks.map((check) => check.claimId)),\n\t\texecutionRequested: false,\n\t});\n}\n\n/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */\nexport class RunCoordinator {\n\tprivate readonly stateRoot: string;\n\tprivate readonly runtime: VerifiedRunRuntime | undefined;\n\tconstructor(stateRoot: string, runtime?: VerifiedRunRuntime) {\n\t\tthis.stateRoot = resolve(stateRoot);\n\t\tthis.runtime = runtime;\n\t}\n\n\tinspect(runId: string): RunProjection {\n\t\tconst journal = readRunJournal(stateRunPath(this.stateRoot, runId));\n\t\tif (!journal || journal.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (journal.state.receiptDigest) this.evidence(runId);\n\t\treturn journal.state;\n\t}\n\n\tinspectRecovery(runId: string): RecoveryInspection {\n\t\tconst report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectWriterRecovery(runId: string): WriterRecoveryInspection {\n\t\tconst report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectTaskRecovery(runId: string): TaskRecoveryInspection {\n\t\tconst report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tasync retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunTaskRetryCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tevidence(runId: string): VerifiedRunEvidence {\n\t\tconst runPath = stateRunPath(this.stateRoot, runId);\n\t\tconst journal = readRunJournal(runPath);\n\t\tconst first = journal?.records[0]?.event;\n\t\tif (!journal || first?.kind !== \"created\" || first.contract.runId !== runId)\n\t\t\tthrow new VerifiedRunError(\"missing_run\");\n\t\treturn readRunEvidence(\n\t\t\trunPath,\n\t\t\tjournal,\n\t\t\tcommandEnvironmentDigest(first.contract, journal.state.budget ? \"gated-v1\" : \"legacy\"),\n\t\t);\n\t}\n\n\tartifact(runId: string, candidateDigest: string, path: string): Buffer {\n\t\tconst evidence = this.evidence(runId);\n\t\tif (!evidence.verified || candidateDigest !== evidence.candidateDigest)\n\t\t\tthrow new VerifiedRunError(\"candidate_mismatch\");\n\t\tconst file = evidence.manifest.files.find((entry) => entry.path === path);\n\t\tif (!file) throw new VerifiedRunError(\"artifact_scope\");\n\t\tconst bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), \"blobs\", file.digest), file.size);\n\t\tif (digestBytes(bytes) !== file.digest || bytes.length !== file.size) throw new VerifiedRunError(\"integrity\");\n\t\treturn bytes;\n\t}\n\n\tasync resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunResumeCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunWriterRestartCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {\n\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t});\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst began = performance.now();\n\t\tconst clock = readRunClock();\n\t\tconst contract = parseRunContract(input);\n\t\tconst command = parseRunStartCommand(request);\n\t\tconst contractDigest = digestObject(contract);\n\t\tif (approval.approvedContractDigest !== contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tif (command.contractDigest !== contractDigest || command.runId !== contract.runId)\n\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\tif (approval.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tassertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);\n\t\tconst runPath = stateRunPath(this.stateRoot, contract.runId);\n\t\tconst existing = readRunJournal(runPath);\n\t\tif (existing) {\n\t\t\tconst first = existing.records[0]?.event;\n\t\t\tif (\n\t\t\t\tfirst?.kind !== \"created\" ||\n\t\t\t\tdigestObject(first.command) !== digestObject(command) ||\n\t\t\t\tdigestObject(first.contract) !== contractDigest\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\t\treturn this.inspect(contract.runId);\n\t\t}\n\t\tconst base = captureCandidate(contract.workspace.root, contract.budget);\n\t\tif (base.digest !== contract.workspace.baseDigest) throw new VerifiedRunError(\"base_conflict\");\n\t\tconst environmentDigest = commandEnvironmentDigest(contract, \"gated-v1\");\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tensureDurableDirectorySync(runPath);\n\t\tconst owner = acquireSessionOwnerLeaseSync(journalPath(runPath));\n\t\ttry {\n\t\t\tif (readRunJournal(runPath)) throw new VerifiedRunError(\"command_conflict\");\n\t\t\tconst journal = new VerifiedRunJournal(runPath, owner);\n\t\t\tjournal.append({ kind: \"created\", contract, command });\n\t\t\tconst budget = anchorRunBudget(contract.budget, clock);\n\t\t\tjournal.append({ kind: \"budget_anchored\", budget, environmentDigest, driver: \"linux-pidns-gate-v1\" });\n\t\t\tconst context: RunPhaseContext = {\n\t\t\t\trunPath,\n\t\t\t\tcontract,\n\t\t\t\tjournal,\n\t\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcreateRunIssuer(runPath);\n\t\t\t\tstoreCandidate(base, runPath);\n\t\t\t\tjournal.append({ kind: \"input_checkpoint\", digest: base.digest });\n\t\t\t\tconst work = join(runPath, \"writer\");\n\t\t\t\tif (contract.profile !== \"linux-command-dag-v1\") materializeCandidate(base, work);\n\t\t\t\tconst workDeadline = began + contract.budget.workMs;\n\t\t\t\tawait executeWriter(context, {\n\t\t\t\t\tworkspace: work,\n\t\t\t\t\tdeadline: workDeadline,\n\t\t\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t\t\t});\n\t\t\t\tif (journal.state.execution === \"paused\") return this.inspect(contract.runId);\n\t\t\t\tpublishWriterCandidate(context, work, workDeadline);\n\t\t\t\tawait verifyCandidate(context);\n\t\t\t\treturn this.inspect(contract.runId);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof VerifiedRunError && !journal.state.receiptDigest)\n\t\t\t\t\treturn journal.append({ kind: \"failed\", code: error.code });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\towner.release();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { parseRunContract, parseRunResumeCommand, parseRunStartCommand, parseRunTaskRetryCommand, parseRunWriterRestartCommand, } from "omk-protocol";
|
|
4
|
+
import { ensureDurableDirectorySync } from "../durable-file-io.js";
|
|
5
|
+
import { acquireSessionOwnerLeaseSync } from "../session-owner-lease.js";
|
|
6
|
+
import { commandEnvironmentDigest, probeVerifiedSandbox } from "./broker.js";
|
|
7
|
+
import { captureCandidate, materializeCandidate, storeCandidate } from "./candidate.js";
|
|
8
|
+
import { preflightCheckReceipts } from "./check-receipt.js";
|
|
9
|
+
import { inspectTaskRecovery, retryDagTasks } from "./dag-recovery.js";
|
|
10
|
+
import { createRunIssuer, readRunEvidence } from "./evidence.js";
|
|
11
|
+
import { journalPath, readRunJournal, VerifiedRunJournal } from "./journal.js";
|
|
12
|
+
import { inspectRunRecovery, resumeFrozenCandidate } from "./recovery.js";
|
|
13
|
+
import { anchorRunBudget, readRunClock } from "./recovery-clock.js";
|
|
14
|
+
import { assertStateOutsideWorkspace, digestBytes, digestObject, readRegularFile, stateRunPath, VerifiedRunError, } from "./storage.js";
|
|
15
|
+
import { verifyCandidate } from "./verification-phase.js";
|
|
16
|
+
import { publishWriterCandidate } from "./writer-completion.js";
|
|
17
|
+
import { executeWriter } from "./writer-phase.js";
|
|
18
|
+
import { inspectWriterRecovery, restartIsolatedWriter } from "./writer-recovery.js";
|
|
19
|
+
export function planVerifiedRun(input) {
|
|
20
|
+
const contract = parseRunContract(input);
|
|
21
|
+
const snapshot = captureCandidate(contract.workspace.root, contract.budget);
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
profile: contract.profile,
|
|
24
|
+
contractDigest: digestObject(contract),
|
|
25
|
+
baseDigest: snapshot.digest,
|
|
26
|
+
baseMatches: snapshot.digest === contract.workspace.baseDigest,
|
|
27
|
+
environmentDigest: commandEnvironmentDigest(contract, "gated-v1"),
|
|
28
|
+
checks: Object.freeze(contract.checks.map((check) => check.claimId)),
|
|
29
|
+
executionRequested: false,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */
|
|
33
|
+
export class RunCoordinator {
|
|
34
|
+
stateRoot;
|
|
35
|
+
runtime;
|
|
36
|
+
constructor(stateRoot, runtime) {
|
|
37
|
+
this.stateRoot = resolve(stateRoot);
|
|
38
|
+
this.runtime = runtime;
|
|
39
|
+
}
|
|
40
|
+
inspect(runId) {
|
|
41
|
+
const journal = readRunJournal(stateRunPath(this.stateRoot, runId));
|
|
42
|
+
if (!journal || journal.state.runId !== runId)
|
|
43
|
+
throw new VerifiedRunError("missing_run");
|
|
44
|
+
if (journal.state.receiptDigest)
|
|
45
|
+
this.evidence(runId);
|
|
46
|
+
return journal.state;
|
|
47
|
+
}
|
|
48
|
+
inspectRecovery(runId) {
|
|
49
|
+
const report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));
|
|
50
|
+
if (report.state.runId !== runId)
|
|
51
|
+
throw new VerifiedRunError("missing_run");
|
|
52
|
+
if (report.state.receiptDigest)
|
|
53
|
+
this.evidence(runId);
|
|
54
|
+
return report;
|
|
55
|
+
}
|
|
56
|
+
inspectWriterRecovery(runId) {
|
|
57
|
+
const report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));
|
|
58
|
+
if (report.state.runId !== runId)
|
|
59
|
+
throw new VerifiedRunError("missing_run");
|
|
60
|
+
if (report.state.receiptDigest)
|
|
61
|
+
this.evidence(runId);
|
|
62
|
+
return report;
|
|
63
|
+
}
|
|
64
|
+
inspectTaskRecovery(runId) {
|
|
65
|
+
const report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));
|
|
66
|
+
if (report.state.runId !== runId)
|
|
67
|
+
throw new VerifiedRunError("missing_run");
|
|
68
|
+
if (report.state.receiptDigest)
|
|
69
|
+
this.evidence(runId);
|
|
70
|
+
return report;
|
|
71
|
+
}
|
|
72
|
+
async retryTasks(input, approval) {
|
|
73
|
+
const command = parseRunTaskRetryCommand(input);
|
|
74
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
75
|
+
throw new VerifiedRunError("approval");
|
|
76
|
+
await retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);
|
|
77
|
+
return this.inspect(command.runId);
|
|
78
|
+
}
|
|
79
|
+
evidence(runId) {
|
|
80
|
+
const runPath = stateRunPath(this.stateRoot, runId);
|
|
81
|
+
const journal = readRunJournal(runPath);
|
|
82
|
+
const first = journal?.records[0]?.event;
|
|
83
|
+
if (!journal || first?.kind !== "created" || first.contract.runId !== runId)
|
|
84
|
+
throw new VerifiedRunError("missing_run");
|
|
85
|
+
return readRunEvidence(runPath, journal, commandEnvironmentDigest(first.contract, journal.state.budget ? "gated-v1" : "legacy"));
|
|
86
|
+
}
|
|
87
|
+
artifact(runId, candidateDigest, path) {
|
|
88
|
+
const evidence = this.evidence(runId);
|
|
89
|
+
if (!evidence.verified || candidateDigest !== evidence.candidateDigest)
|
|
90
|
+
throw new VerifiedRunError("candidate_mismatch");
|
|
91
|
+
const file = evidence.manifest.files.find((entry) => entry.path === path);
|
|
92
|
+
if (!file)
|
|
93
|
+
throw new VerifiedRunError("artifact_scope");
|
|
94
|
+
const bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), "blobs", file.digest), file.size);
|
|
95
|
+
if (digestBytes(bytes) !== file.digest || bytes.length !== file.size)
|
|
96
|
+
throw new VerifiedRunError("integrity");
|
|
97
|
+
return bytes;
|
|
98
|
+
}
|
|
99
|
+
async resume(input, approval) {
|
|
100
|
+
const command = parseRunResumeCommand(input);
|
|
101
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
102
|
+
throw new VerifiedRunError("approval");
|
|
103
|
+
await resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);
|
|
104
|
+
return this.inspect(command.runId);
|
|
105
|
+
}
|
|
106
|
+
async restartWriter(input, approval) {
|
|
107
|
+
const command = parseRunWriterRestartCommand(input);
|
|
108
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
109
|
+
throw new VerifiedRunError("approval");
|
|
110
|
+
await restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {
|
|
111
|
+
...(approval.signal ? { signal: approval.signal } : {}),
|
|
112
|
+
...(this.runtime ? { runtime: this.runtime } : {}),
|
|
113
|
+
});
|
|
114
|
+
return this.inspect(command.runId);
|
|
115
|
+
}
|
|
116
|
+
async start(input, request, approval) {
|
|
117
|
+
const began = performance.now();
|
|
118
|
+
const clock = readRunClock();
|
|
119
|
+
const contract = parseRunContract(input);
|
|
120
|
+
const command = parseRunStartCommand(request);
|
|
121
|
+
const contractDigest = digestObject(contract);
|
|
122
|
+
if (approval.approvedContractDigest !== contractDigest)
|
|
123
|
+
throw new VerifiedRunError("approval");
|
|
124
|
+
if (command.contractDigest !== contractDigest || command.runId !== contract.runId)
|
|
125
|
+
throw new VerifiedRunError("command_conflict");
|
|
126
|
+
if (approval.signal?.aborted)
|
|
127
|
+
throw new VerifiedRunError("cancelled");
|
|
128
|
+
assertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);
|
|
129
|
+
const runPath = stateRunPath(this.stateRoot, contract.runId);
|
|
130
|
+
const existing = readRunJournal(runPath);
|
|
131
|
+
if (existing) {
|
|
132
|
+
const first = existing.records[0]?.event;
|
|
133
|
+
if (first?.kind !== "created" ||
|
|
134
|
+
digestObject(first.command) !== digestObject(command) ||
|
|
135
|
+
digestObject(first.contract) !== contractDigest)
|
|
136
|
+
throw new VerifiedRunError("command_conflict");
|
|
137
|
+
return this.inspect(contract.runId);
|
|
138
|
+
}
|
|
139
|
+
const base = captureCandidate(contract.workspace.root, contract.budget);
|
|
140
|
+
if (base.digest !== contract.workspace.baseDigest)
|
|
141
|
+
throw new VerifiedRunError("base_conflict");
|
|
142
|
+
const environmentDigest = commandEnvironmentDigest(contract, "gated-v1");
|
|
143
|
+
preflightCheckReceipts(contract);
|
|
144
|
+
probeVerifiedSandbox();
|
|
145
|
+
ensureDurableDirectorySync(runPath);
|
|
146
|
+
const owner = acquireSessionOwnerLeaseSync(journalPath(runPath));
|
|
147
|
+
try {
|
|
148
|
+
if (readRunJournal(runPath))
|
|
149
|
+
throw new VerifiedRunError("command_conflict");
|
|
150
|
+
const journal = new VerifiedRunJournal(runPath, owner);
|
|
151
|
+
journal.append({ kind: "created", contract, command });
|
|
152
|
+
const budget = anchorRunBudget(contract.budget, clock);
|
|
153
|
+
journal.append({ kind: "budget_anchored", budget, environmentDigest, driver: "linux-pidns-gate-v1" });
|
|
154
|
+
const context = {
|
|
155
|
+
runPath,
|
|
156
|
+
contract,
|
|
157
|
+
journal,
|
|
158
|
+
...(approval.signal ? { signal: approval.signal } : {}),
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
createRunIssuer(runPath);
|
|
162
|
+
storeCandidate(base, runPath);
|
|
163
|
+
journal.append({ kind: "input_checkpoint", digest: base.digest });
|
|
164
|
+
const work = join(runPath, "writer");
|
|
165
|
+
if (contract.profile !== "linux-command-dag-v1")
|
|
166
|
+
materializeCandidate(base, work);
|
|
167
|
+
const workDeadline = began + contract.budget.workMs;
|
|
168
|
+
await executeWriter(context, {
|
|
169
|
+
workspace: work,
|
|
170
|
+
deadline: workDeadline,
|
|
171
|
+
...(this.runtime ? { runtime: this.runtime } : {}),
|
|
172
|
+
});
|
|
173
|
+
if (journal.state.execution === "paused")
|
|
174
|
+
return this.inspect(contract.runId);
|
|
175
|
+
publishWriterCandidate(context, work, workDeadline);
|
|
176
|
+
await verifyCandidate(context);
|
|
177
|
+
return this.inspect(contract.runId);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (error instanceof VerifiedRunError && !journal.state.receiptDigest)
|
|
181
|
+
return journal.append({ kind: "failed", code: error.code });
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
owner.release();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=coordinator.js.map
|