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 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/core/verified-run/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { RunContract } from \"omk-protocol\";\nimport type { EvidenceReceipt } from \"../../types/evidence.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport { type CandidateManifest, loadCandidate } from \"./candidate.ts\";\nimport { readCheckReceipts } from \"./check-receipt.ts\";\nimport { type CheckObservation, closesRunClaims, parseCheckObservations } from \"./evidence-binding.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\nexport type { CheckObservation } from \"./evidence-binding.ts\";\n\ninterface Attestation {\n\treadonly version: 1 | 2 | 3;\n\treadonly runId: string;\n\treadonly generation: number;\n\treadonly contractDigest: string;\n\treadonly candidateDigest: string;\n\treadonly environmentDigest: string;\n\treadonly verifierDigest: string;\n\treadonly checks: readonly CheckObservation[];\n\treadonly verified: boolean;\n}\nexport interface VerifiedRunEvidence {\n\treadonly candidateDigest: string;\n\treadonly manifest: CandidateManifest;\n\treadonly receiptDigest: string;\n\treadonly verified: boolean;\n\treadonly checks: readonly CheckObservation[];\n\treadonly receiptFormat: \"v3\" | \"legacy\";\n\treadonly receipts: readonly EvidenceReceipt[];\n}\n\nexport function createRunIssuer(runPath: string): void {\n\t// Recovery must never replace a missing key and re-sign old evidence.\n\tpublishBytes(join(runPath, \"issuer.key\"), randomBytes(32));\n}\n\nfunction tag(runPath: string, receipt: unknown): Buffer {\n\tconst key = readRegularFile(join(runPath, \"issuer.key\"), 32);\n\tif (key.length !== 32) throw new VerifiedRunError(\"integrity\");\n\treturn createHmac(\"sha256\", key).update(\"omk.verified-run.attestation.v1\\0\").update(canonicalJson(receipt)).digest();\n}\n\nexport function issueRunEvidence(\n\trunPath: string,\n\tcontract: RunContract,\n\tmaterial: {\n\t\treadonly generation: number;\n\t\treadonly candidateDigest: string;\n\t\treadonly environmentDigest: string;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): { readonly digest: string; readonly verified: boolean } {\n\tconst checks = parseCheckObservations(material.checks, true);\n\tconst candidate = loadCandidate(runPath, material.candidateDigest, contract.budget);\n\treadCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks });\n\tconst receipt: Attestation = {\n\t\tversion: 3,\n\t\trunId: contract.runId,\n\t\tgeneration: material.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest: material.candidateDigest,\n\t\tenvironmentDigest: material.environmentDigest,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified: closesRunClaims(contract, {\n\t\t\tcandidate: material.candidateDigest,\n\t\t\tenvironment: material.environmentDigest,\n\t\t\tchecks,\n\t\t}),\n\t};\n\tconst envelope = { receipt, authenticationTag: tag(runPath, receipt).toString(\"hex\") };\n\tconst digest = digestObject(envelope);\n\tpublishObject(join(runPath, \"attestations\", `${digest}.json`), envelope);\n\treturn { digest, verified: receipt.verified };\n}\n\nexport function readRunEvidence(runPath: string, journal: JournalSnapshot, environment: string): VerifiedRunEvidence {\n\tconst first = journal.records[0]?.event;\n\tconst { candidateDigest, receiptDigest } = journal.state;\n\tif (first?.kind !== \"created\" || !candidateDigest || !receiptDigest) throw new VerifiedRunError(\"evidence_missing\");\n\tconst raw = readJson(join(runPath, \"attestations\", `${receiptDigest}.json`));\n\tif (\n\t\tdigestObject(raw) !== receiptDigest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"receipt\" in raw) ||\n\t\t!(\"authenticationTag\" in raw) ||\n\t\ttypeof raw.authenticationTag !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(raw.authenticationTag) ||\n\t\t!timingSafeEqual(tag(runPath, raw.receipt), Buffer.from(raw.authenticationTag, \"hex\"))\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst receipt = raw.receipt;\n\tif (\n\t\ttypeof receipt !== \"object\" ||\n\t\treceipt === null ||\n\t\t!(\"checks\" in receipt) ||\n\t\t!(\"version\" in receipt) ||\n\t\t(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst checks = parseCheckObservations(receipt.checks, receipt.version !== 1);\n\tconst contract = first.contract;\n\tconst dispatches = journal.records.flatMap(({ event, generation }) =>\n\t\tgeneration === journal.state.generation && event.kind === \"dispatch\" && event.role === \"verifier\" ? [event] : [],\n\t);\n\tif (\n\t\tchecks.length !== contract.checks.length ||\n\t\tchecks.length !== dispatches.length ||\n\t\tnew Set(checks.map((check) => check.claimId)).size !== checks.length ||\n\t\tchecks.some(\n\t\t\t(check) =>\n\t\t\t\t!dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst verified = closesRunClaims(contract, { candidate: candidateDigest, environment, checks });\n\tconst expected: Attestation = {\n\t\tversion: receipt.version,\n\t\trunId: contract.runId,\n\t\tgeneration: journal.state.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest,\n\t\tenvironmentDigest: environment,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified,\n\t};\n\tif (canonicalJson(receipt) !== canonicalJson(expected) || verified !== (journal.state.verification === \"verified\"))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst candidate = loadCandidate(runPath, candidateDigest, contract.budget);\n\tconst receipts =\n\t\treceipt.version !== 1\n\t\t\t? readCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks })\n\t\t\t: Object.freeze([]);\n\treturn Object.freeze({\n\t\tcandidateDigest,\n\t\tmanifest: candidate.manifest,\n\t\treceiptDigest,\n\t\tverified,\n\t\tchecks,\n\t\treceiptFormat: receipt.version !== 1 ? \"v3\" : \"legacy\",\n\t\treceipts,\n\t});\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { appendFileDurablySync } from "../durable-file-io.ts";
|
|
2
|
+
import type { SessionOwnerLease } from "../session-owner-lease.ts";
|
|
3
|
+
import { type RunEvent, type RunProjection } from "./events.ts";
|
|
4
|
+
interface RecordV2 {
|
|
5
|
+
readonly version: 2;
|
|
6
|
+
readonly seq: number;
|
|
7
|
+
readonly generation: number;
|
|
8
|
+
readonly previous: string;
|
|
9
|
+
readonly event: RunEvent;
|
|
10
|
+
readonly hash: string;
|
|
11
|
+
}
|
|
12
|
+
export interface JournalSnapshot {
|
|
13
|
+
readonly records: readonly RecordV2[];
|
|
14
|
+
readonly state: RunProjection;
|
|
15
|
+
readonly bytesDigest: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const journalPath: (runPath: string) => string;
|
|
18
|
+
/** Read-only: no implicit recovery, tail truncation, mode changes, or model calls. */
|
|
19
|
+
export declare function readRunJournal(runPath: string): JournalSnapshot | null;
|
|
20
|
+
/** v2 event store reuses the v1 durable append and mutation/owner locking primitives. */
|
|
21
|
+
export declare class VerifiedRunJournal {
|
|
22
|
+
private head;
|
|
23
|
+
private poisoned;
|
|
24
|
+
private readonly runPath;
|
|
25
|
+
private readonly owner;
|
|
26
|
+
private readonly persist;
|
|
27
|
+
constructor(runPath: string, owner: SessionOwnerLease, persist?: typeof appendFileDurablySync);
|
|
28
|
+
get state(): RunProjection;
|
|
29
|
+
append(event: RunEvent): RunProjection;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/journal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAA6B,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3F,UAAU,QAAQ;IACjB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AACD,eAAO,MAAM,WAAW,6BAAiE,CAAC;AAE1F,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA+BtE;AAED,yFAAyF;AACzF,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,IAAI,CAAyB;IACrC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IAEpE,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,+BAAwB,EAKrF;IAED,IAAI,KAAK,IAAI,aAAa,CAGzB;IAED,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,CA+BrC;CACD","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { acquireDurableFileMutationLockSync } from \"../durable-file-identity.ts\";\nimport { appendFileDurablySync } from \"../durable-file-io.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport type { SessionOwnerLease } from \"../session-owner-lease.ts\";\nimport { parseRunEvent, projectRun, type RunEvent, type RunProjection } from \"./events.ts\";\nimport { digestBytes, digestObject, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\ninterface RecordV2 {\n\treadonly version: 2;\n\treadonly seq: number;\n\treadonly generation: number;\n\treadonly previous: string;\n\treadonly event: RunEvent;\n\treadonly hash: string;\n}\nexport interface JournalSnapshot {\n\treadonly records: readonly RecordV2[];\n\treadonly state: RunProjection;\n\treadonly bytesDigest: string;\n}\nexport const journalPath = (runPath: string): string => join(runPath, \"journal.v2.jsonl\");\n\n/** Read-only: no implicit recovery, tail truncation, mode changes, or model calls. */\nexport function readRunJournal(runPath: string): JournalSnapshot | null {\n\tconst path = journalPath(runPath);\n\tif (!existsSync(path)) return null;\n\tconst bytes = readRegularFile(path, 8388608);\n\tif (!bytes.length || bytes.at(-1) !== 10) throw new VerifiedRunError(\"journal_truncated\");\n\tconst lines = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes).slice(0, -1).split(\"\\n\");\n\tconst records: RecordV2[] = [];\n\tlet previous = \"0\".repeat(64);\n\tlet generation = 1;\n\tfor (const [index, line] of lines.entries()) {\n\t\tlet raw: unknown;\n\t\ttry {\n\t\t\traw = JSON.parse(line);\n\t\t} catch {\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t}\n\t\tif (typeof raw !== \"object\" || raw === null || !(\"event\" in raw)) throw new VerifiedRunError(\"integrity\");\n\t\tconst event = parseRunEvent(raw.event);\n\t\tif (event.kind === \"resumed\" || event.kind === \"writer_restarted\" || event.kind === \"tasks_retried\")\n\t\t\tgeneration += 1;\n\t\tconst material = { version: 2 as const, seq: index + 1, generation, previous, event };\n\t\tconst record = Object.freeze({ ...material, hash: digestObject(material) });\n\t\tif (canonicalJson(raw) !== canonicalJson(record)) throw new VerifiedRunError(\"integrity\");\n\t\trecords.push(record);\n\t\tprevious = record.hash;\n\t}\n\treturn {\n\t\trecords: Object.freeze(records),\n\t\tstate: projectRun(records.map((record) => record.event)),\n\t\tbytesDigest: digestBytes(bytes),\n\t};\n}\n\n/** v2 event store reuses the v1 durable append and mutation/owner locking primitives. */\nexport class VerifiedRunJournal {\n\tprivate head: JournalSnapshot | null;\n\tprivate poisoned = false;\n\tprivate readonly runPath: string;\n\tprivate readonly owner: SessionOwnerLease;\n\tprivate readonly persist: (path: string, bytes: Uint8Array) => void;\n\n\tconstructor(runPath: string, owner: SessionOwnerLease, persist = appendFileDurablySync) {\n\t\tthis.runPath = runPath;\n\t\tthis.owner = owner;\n\t\tthis.persist = persist;\n\t\tthis.head = readRunJournal(runPath);\n\t}\n\n\tget state(): RunProjection {\n\t\tif (!this.head) throw new VerifiedRunError(\"missing_run\");\n\t\treturn this.head.state;\n\t}\n\n\tappend(event: RunEvent): RunProjection {\n\t\tconst path = journalPath(this.runPath);\n\t\tif (this.poisoned || !this.owner.owns(path)) throw new VerifiedRunError(\"stale_owner\");\n\t\tconst lock = acquireDurableFileMutationLockSync(path);\n\t\ttry {\n\t\t\tconst current = readRunJournal(this.runPath);\n\t\t\tif (current?.bytesDigest !== this.head?.bytesDigest) throw new VerifiedRunError(\"stale_revision\");\n\t\t\tconst records = current?.records ?? [];\n\t\t\tconst candidate = projectRun([...records.map((record) => record.event), event]);\n\t\t\tconst material = {\n\t\t\t\tversion: 2 as const,\n\t\t\t\tseq: records.length + 1,\n\t\t\t\tgeneration: candidate.generation,\n\t\t\t\tprevious: records.at(-1)?.hash ?? \"0\".repeat(64),\n\t\t\t\tevent,\n\t\t\t};\n\t\t\tconst record: RecordV2 = { ...material, hash: digestObject(material) };\n\t\t\ttry {\n\t\t\t\tthis.persist(path, Buffer.from(`${canonicalJson(record)}\\n`));\n\t\t\t\tconst next = readRunJournal(this.runPath);\n\t\t\t\tif (!next || next.records.at(-1)?.hash !== record.hash) throw new VerifiedRunError(\"integrity\");\n\t\t\t\tthis.owner.refresh(true);\n\t\t\t\tthis.head = next;\n\t\t\t} catch (error) {\n\t\t\t\tthis.poisoned = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn this.state;\n\t\t} finally {\n\t\t\tlock.release();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { acquireDurableFileMutationLockSync } from "../durable-file-identity.js";
|
|
4
|
+
import { appendFileDurablySync } from "../durable-file-io.js";
|
|
5
|
+
import { canonicalJson } from "../run-journal.js";
|
|
6
|
+
import { parseRunEvent, projectRun } from "./events.js";
|
|
7
|
+
import { digestBytes, digestObject, readRegularFile, VerifiedRunError } from "./storage.js";
|
|
8
|
+
export const journalPath = (runPath) => join(runPath, "journal.v2.jsonl");
|
|
9
|
+
/** Read-only: no implicit recovery, tail truncation, mode changes, or model calls. */
|
|
10
|
+
export function readRunJournal(runPath) {
|
|
11
|
+
const path = journalPath(runPath);
|
|
12
|
+
if (!existsSync(path))
|
|
13
|
+
return null;
|
|
14
|
+
const bytes = readRegularFile(path, 8388608);
|
|
15
|
+
if (!bytes.length || bytes.at(-1) !== 10)
|
|
16
|
+
throw new VerifiedRunError("journal_truncated");
|
|
17
|
+
const lines = new TextDecoder("utf-8", { fatal: true }).decode(bytes).slice(0, -1).split("\n");
|
|
18
|
+
const records = [];
|
|
19
|
+
let previous = "0".repeat(64);
|
|
20
|
+
let generation = 1;
|
|
21
|
+
for (const [index, line] of lines.entries()) {
|
|
22
|
+
let raw;
|
|
23
|
+
try {
|
|
24
|
+
raw = JSON.parse(line);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new VerifiedRunError("integrity");
|
|
28
|
+
}
|
|
29
|
+
if (typeof raw !== "object" || raw === null || !("event" in raw))
|
|
30
|
+
throw new VerifiedRunError("integrity");
|
|
31
|
+
const event = parseRunEvent(raw.event);
|
|
32
|
+
if (event.kind === "resumed" || event.kind === "writer_restarted" || event.kind === "tasks_retried")
|
|
33
|
+
generation += 1;
|
|
34
|
+
const material = { version: 2, seq: index + 1, generation, previous, event };
|
|
35
|
+
const record = Object.freeze({ ...material, hash: digestObject(material) });
|
|
36
|
+
if (canonicalJson(raw) !== canonicalJson(record))
|
|
37
|
+
throw new VerifiedRunError("integrity");
|
|
38
|
+
records.push(record);
|
|
39
|
+
previous = record.hash;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
records: Object.freeze(records),
|
|
43
|
+
state: projectRun(records.map((record) => record.event)),
|
|
44
|
+
bytesDigest: digestBytes(bytes),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** v2 event store reuses the v1 durable append and mutation/owner locking primitives. */
|
|
48
|
+
export class VerifiedRunJournal {
|
|
49
|
+
head;
|
|
50
|
+
poisoned = false;
|
|
51
|
+
runPath;
|
|
52
|
+
owner;
|
|
53
|
+
persist;
|
|
54
|
+
constructor(runPath, owner, persist = appendFileDurablySync) {
|
|
55
|
+
this.runPath = runPath;
|
|
56
|
+
this.owner = owner;
|
|
57
|
+
this.persist = persist;
|
|
58
|
+
this.head = readRunJournal(runPath);
|
|
59
|
+
}
|
|
60
|
+
get state() {
|
|
61
|
+
if (!this.head)
|
|
62
|
+
throw new VerifiedRunError("missing_run");
|
|
63
|
+
return this.head.state;
|
|
64
|
+
}
|
|
65
|
+
append(event) {
|
|
66
|
+
const path = journalPath(this.runPath);
|
|
67
|
+
if (this.poisoned || !this.owner.owns(path))
|
|
68
|
+
throw new VerifiedRunError("stale_owner");
|
|
69
|
+
const lock = acquireDurableFileMutationLockSync(path);
|
|
70
|
+
try {
|
|
71
|
+
const current = readRunJournal(this.runPath);
|
|
72
|
+
if (current?.bytesDigest !== this.head?.bytesDigest)
|
|
73
|
+
throw new VerifiedRunError("stale_revision");
|
|
74
|
+
const records = current?.records ?? [];
|
|
75
|
+
const candidate = projectRun([...records.map((record) => record.event), event]);
|
|
76
|
+
const material = {
|
|
77
|
+
version: 2,
|
|
78
|
+
seq: records.length + 1,
|
|
79
|
+
generation: candidate.generation,
|
|
80
|
+
previous: records.at(-1)?.hash ?? "0".repeat(64),
|
|
81
|
+
event,
|
|
82
|
+
};
|
|
83
|
+
const record = { ...material, hash: digestObject(material) };
|
|
84
|
+
try {
|
|
85
|
+
this.persist(path, Buffer.from(`${canonicalJson(record)}\n`));
|
|
86
|
+
const next = readRunJournal(this.runPath);
|
|
87
|
+
if (!next || next.records.at(-1)?.hash !== record.hash)
|
|
88
|
+
throw new VerifiedRunError("integrity");
|
|
89
|
+
this.owner.refresh(true);
|
|
90
|
+
this.head = next;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.poisoned = true;
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
return this.state;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
lock.release();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../../src/core/verified-run/journal.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { acquireDurableFileMutationLockSync } from \"../durable-file-identity.ts\";\nimport { appendFileDurablySync } from \"../durable-file-io.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport type { SessionOwnerLease } from \"../session-owner-lease.ts\";\nimport { parseRunEvent, projectRun, type RunEvent, type RunProjection } from \"./events.ts\";\nimport { digestBytes, digestObject, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\ninterface RecordV2 {\n\treadonly version: 2;\n\treadonly seq: number;\n\treadonly generation: number;\n\treadonly previous: string;\n\treadonly event: RunEvent;\n\treadonly hash: string;\n}\nexport interface JournalSnapshot {\n\treadonly records: readonly RecordV2[];\n\treadonly state: RunProjection;\n\treadonly bytesDigest: string;\n}\nexport const journalPath = (runPath: string): string => join(runPath, \"journal.v2.jsonl\");\n\n/** Read-only: no implicit recovery, tail truncation, mode changes, or model calls. */\nexport function readRunJournal(runPath: string): JournalSnapshot | null {\n\tconst path = journalPath(runPath);\n\tif (!existsSync(path)) return null;\n\tconst bytes = readRegularFile(path, 8388608);\n\tif (!bytes.length || bytes.at(-1) !== 10) throw new VerifiedRunError(\"journal_truncated\");\n\tconst lines = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes).slice(0, -1).split(\"\\n\");\n\tconst records: RecordV2[] = [];\n\tlet previous = \"0\".repeat(64);\n\tlet generation = 1;\n\tfor (const [index, line] of lines.entries()) {\n\t\tlet raw: unknown;\n\t\ttry {\n\t\t\traw = JSON.parse(line);\n\t\t} catch {\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t}\n\t\tif (typeof raw !== \"object\" || raw === null || !(\"event\" in raw)) throw new VerifiedRunError(\"integrity\");\n\t\tconst event = parseRunEvent(raw.event);\n\t\tif (event.kind === \"resumed\" || event.kind === \"writer_restarted\" || event.kind === \"tasks_retried\")\n\t\t\tgeneration += 1;\n\t\tconst material = { version: 2 as const, seq: index + 1, generation, previous, event };\n\t\tconst record = Object.freeze({ ...material, hash: digestObject(material) });\n\t\tif (canonicalJson(raw) !== canonicalJson(record)) throw new VerifiedRunError(\"integrity\");\n\t\trecords.push(record);\n\t\tprevious = record.hash;\n\t}\n\treturn {\n\t\trecords: Object.freeze(records),\n\t\tstate: projectRun(records.map((record) => record.event)),\n\t\tbytesDigest: digestBytes(bytes),\n\t};\n}\n\n/** v2 event store reuses the v1 durable append and mutation/owner locking primitives. */\nexport class VerifiedRunJournal {\n\tprivate head: JournalSnapshot | null;\n\tprivate poisoned = false;\n\tprivate readonly runPath: string;\n\tprivate readonly owner: SessionOwnerLease;\n\tprivate readonly persist: (path: string, bytes: Uint8Array) => void;\n\n\tconstructor(runPath: string, owner: SessionOwnerLease, persist = appendFileDurablySync) {\n\t\tthis.runPath = runPath;\n\t\tthis.owner = owner;\n\t\tthis.persist = persist;\n\t\tthis.head = readRunJournal(runPath);\n\t}\n\n\tget state(): RunProjection {\n\t\tif (!this.head) throw new VerifiedRunError(\"missing_run\");\n\t\treturn this.head.state;\n\t}\n\n\tappend(event: RunEvent): RunProjection {\n\t\tconst path = journalPath(this.runPath);\n\t\tif (this.poisoned || !this.owner.owns(path)) throw new VerifiedRunError(\"stale_owner\");\n\t\tconst lock = acquireDurableFileMutationLockSync(path);\n\t\ttry {\n\t\t\tconst current = readRunJournal(this.runPath);\n\t\t\tif (current?.bytesDigest !== this.head?.bytesDigest) throw new VerifiedRunError(\"stale_revision\");\n\t\t\tconst records = current?.records ?? [];\n\t\t\tconst candidate = projectRun([...records.map((record) => record.event), event]);\n\t\t\tconst material = {\n\t\t\t\tversion: 2 as const,\n\t\t\t\tseq: records.length + 1,\n\t\t\t\tgeneration: candidate.generation,\n\t\t\t\tprevious: records.at(-1)?.hash ?? \"0\".repeat(64),\n\t\t\t\tevent,\n\t\t\t};\n\t\t\tconst record: RecordV2 = { ...material, hash: digestObject(material) };\n\t\t\ttry {\n\t\t\t\tthis.persist(path, Buffer.from(`${canonicalJson(record)}\\n`));\n\t\t\t\tconst next = readRunJournal(this.runPath);\n\t\t\t\tif (!next || next.records.at(-1)?.hash !== record.hash) throw new VerifiedRunError(\"integrity\");\n\t\t\t\tthis.owner.refresh(true);\n\t\t\t\tthis.head = next;\n\t\t\t} catch (error) {\n\t\t\t\tthis.poisoned = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn this.state;\n\t\t} finally {\n\t\t\tlock.release();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface NamespaceIdentity {
|
|
2
|
+
readonly pid: number;
|
|
3
|
+
readonly startTicks: string;
|
|
4
|
+
readonly namespace: string;
|
|
5
|
+
readonly bootId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseNamespaceIdentity(raw: unknown): NamespaceIdentity;
|
|
8
|
+
export declare function captureNamespaceIdentity(pid: number): NamespaceIdentity;
|
|
9
|
+
/** Read only. Never signal a PID that may have been reused by another process. */
|
|
10
|
+
export declare function probeNamespace(identity: NamespaceIdentity): "alive" | "gone" | "unknown";
|
|
11
|
+
//# sourceMappingURL=namespace-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-identity.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/namespace-identity.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAqBtE;AAcD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAevE;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAiBxF","sourcesContent":["import { readFileSync, readlinkSync } from \"node:fs\";\nimport { readRunClock } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport interface NamespaceIdentity {\n\treadonly pid: number;\n\treadonly startTicks: string;\n\treadonly namespace: string;\n\treadonly bootId: string;\n}\n\nexport function parseNamespaceIdentity(raw: unknown): NamespaceIdentity {\n\tif (\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"pid\" in raw) ||\n\t\ttypeof raw.pid !== \"number\" ||\n\t\t!Number.isSafeInteger(raw.pid) ||\n\t\traw.pid <= 0 ||\n\t\t!(\"startTicks\" in raw) ||\n\t\ttypeof raw.startTicks !== \"string\" ||\n\t\t!/^\\d+$/.test(raw.startTicks) ||\n\t\traw.startTicks.length > 32 ||\n\t\t!(\"namespace\" in raw) ||\n\t\ttypeof raw.namespace !== \"string\" ||\n\t\t!/^pid:\\[\\d+\\]$/.test(raw.namespace) ||\n\t\t!(\"bootId\" in raw) ||\n\t\ttypeof raw.bootId !== \"string\" ||\n\t\t!/^[a-f0-9-]{36}$/.test(raw.bootId)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\treturn Object.freeze({ pid: raw.pid, startTicks: raw.startTicks, namespace: raw.namespace, bootId: raw.bootId });\n}\n\nfunction processStat(pid: number): { readonly startTicks: string; readonly state: string } {\n\tconst stat = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n\tconst fields = stat\n\t\t.slice(stat.lastIndexOf(\")\") + 2)\n\t\t.trim()\n\t\t.split(/\\s+/);\n\tconst startTicks = fields[19];\n\tconst state = fields[0];\n\tif (!startTicks || !/^\\d+$/.test(startTicks) || !state) throw new VerifiedRunError(\"process_identity\");\n\treturn { startTicks, state };\n}\n\nexport function captureNamespaceIdentity(pid: number): NamespaceIdentity {\n\tif (!Number.isSafeInteger(pid) || pid <= 0) throw new VerifiedRunError(\"process_identity\");\n\tconst before = processStat(pid);\n\tconst status = readFileSync(`/proc/${pid}/status`, \"utf8\");\n\tconst namespacePids = status\n\t\t.match(/^NSpid:\\s+(.+)$/m)?.[1]\n\t\t?.trim()\n\t\t.split(/\\s+/);\n\tif (!namespacePids || namespacePids.length < 2 || namespacePids.at(-1) !== \"1\")\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\tconst namespace = readlinkSync(`/proc/${pid}/ns/pid`);\n\tconst after = processStat(pid);\n\tif (before.startTicks !== after.startTicks || before.state === \"Z\" || after.state === \"Z\")\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\treturn parseNamespaceIdentity({ pid, startTicks: before.startTicks, namespace, bootId: readRunClock().bootId });\n}\n\n/** Read only. Never signal a PID that may have been reused by another process. */\nexport function probeNamespace(identity: NamespaceIdentity): \"alive\" | \"gone\" | \"unknown\" {\n\ttry {\n\t\tif (readRunClock().bootId !== identity.bootId) return \"unknown\";\n\t} catch {\n\t\treturn \"unknown\";\n\t}\n\ttry {\n\t\tconst current = processStat(identity.pid);\n\t\tif (current.startTicks !== identity.startTicks) return \"gone\";\n\t\t// Linux finishes PID namespace teardown before its init becomes a zombie.\n\t\tif (current.state === \"Z\" || current.state === \"X\") return \"gone\";\n\t\treturn readlinkSync(`/proc/${identity.pid}/ns/pid`) === identity.namespace ? \"alive\" : \"unknown\";\n\t} catch (error) {\n\t\tif (error instanceof Error && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ESRCH\"))\n\t\t\treturn \"gone\";\n\t\treturn \"unknown\";\n\t}\n}\n"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFileSync, readlinkSync } from "node:fs";
|
|
2
|
+
import { readRunClock } from "./recovery-clock.js";
|
|
3
|
+
import { VerifiedRunError } from "./storage.js";
|
|
4
|
+
export function parseNamespaceIdentity(raw) {
|
|
5
|
+
if (typeof raw !== "object" ||
|
|
6
|
+
raw === null ||
|
|
7
|
+
!("pid" in raw) ||
|
|
8
|
+
typeof raw.pid !== "number" ||
|
|
9
|
+
!Number.isSafeInteger(raw.pid) ||
|
|
10
|
+
raw.pid <= 0 ||
|
|
11
|
+
!("startTicks" in raw) ||
|
|
12
|
+
typeof raw.startTicks !== "string" ||
|
|
13
|
+
!/^\d+$/.test(raw.startTicks) ||
|
|
14
|
+
raw.startTicks.length > 32 ||
|
|
15
|
+
!("namespace" in raw) ||
|
|
16
|
+
typeof raw.namespace !== "string" ||
|
|
17
|
+
!/^pid:\[\d+\]$/.test(raw.namespace) ||
|
|
18
|
+
!("bootId" in raw) ||
|
|
19
|
+
typeof raw.bootId !== "string" ||
|
|
20
|
+
!/^[a-f0-9-]{36}$/.test(raw.bootId))
|
|
21
|
+
throw new VerifiedRunError("integrity");
|
|
22
|
+
return Object.freeze({ pid: raw.pid, startTicks: raw.startTicks, namespace: raw.namespace, bootId: raw.bootId });
|
|
23
|
+
}
|
|
24
|
+
function processStat(pid) {
|
|
25
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
26
|
+
const fields = stat
|
|
27
|
+
.slice(stat.lastIndexOf(")") + 2)
|
|
28
|
+
.trim()
|
|
29
|
+
.split(/\s+/);
|
|
30
|
+
const startTicks = fields[19];
|
|
31
|
+
const state = fields[0];
|
|
32
|
+
if (!startTicks || !/^\d+$/.test(startTicks) || !state)
|
|
33
|
+
throw new VerifiedRunError("process_identity");
|
|
34
|
+
return { startTicks, state };
|
|
35
|
+
}
|
|
36
|
+
export function captureNamespaceIdentity(pid) {
|
|
37
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
38
|
+
throw new VerifiedRunError("process_identity");
|
|
39
|
+
const before = processStat(pid);
|
|
40
|
+
const status = readFileSync(`/proc/${pid}/status`, "utf8");
|
|
41
|
+
const namespacePids = status
|
|
42
|
+
.match(/^NSpid:\s+(.+)$/m)?.[1]
|
|
43
|
+
?.trim()
|
|
44
|
+
.split(/\s+/);
|
|
45
|
+
if (!namespacePids || namespacePids.length < 2 || namespacePids.at(-1) !== "1")
|
|
46
|
+
throw new VerifiedRunError("process_identity");
|
|
47
|
+
const namespace = readlinkSync(`/proc/${pid}/ns/pid`);
|
|
48
|
+
const after = processStat(pid);
|
|
49
|
+
if (before.startTicks !== after.startTicks || before.state === "Z" || after.state === "Z")
|
|
50
|
+
throw new VerifiedRunError("process_identity");
|
|
51
|
+
return parseNamespaceIdentity({ pid, startTicks: before.startTicks, namespace, bootId: readRunClock().bootId });
|
|
52
|
+
}
|
|
53
|
+
/** Read only. Never signal a PID that may have been reused by another process. */
|
|
54
|
+
export function probeNamespace(identity) {
|
|
55
|
+
try {
|
|
56
|
+
if (readRunClock().bootId !== identity.bootId)
|
|
57
|
+
return "unknown";
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return "unknown";
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const current = processStat(identity.pid);
|
|
64
|
+
if (current.startTicks !== identity.startTicks)
|
|
65
|
+
return "gone";
|
|
66
|
+
// Linux finishes PID namespace teardown before its init becomes a zombie.
|
|
67
|
+
if (current.state === "Z" || current.state === "X")
|
|
68
|
+
return "gone";
|
|
69
|
+
return readlinkSync(`/proc/${identity.pid}/ns/pid`) === identity.namespace ? "alive" : "unknown";
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ESRCH"))
|
|
73
|
+
return "gone";
|
|
74
|
+
return "unknown";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=namespace-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-identity.js","sourceRoot":"","sources":["../../../src/core/verified-run/namespace-identity.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, readlinkSync } from \"node:fs\";\nimport { readRunClock } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport interface NamespaceIdentity {\n\treadonly pid: number;\n\treadonly startTicks: string;\n\treadonly namespace: string;\n\treadonly bootId: string;\n}\n\nexport function parseNamespaceIdentity(raw: unknown): NamespaceIdentity {\n\tif (\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"pid\" in raw) ||\n\t\ttypeof raw.pid !== \"number\" ||\n\t\t!Number.isSafeInteger(raw.pid) ||\n\t\traw.pid <= 0 ||\n\t\t!(\"startTicks\" in raw) ||\n\t\ttypeof raw.startTicks !== \"string\" ||\n\t\t!/^\\d+$/.test(raw.startTicks) ||\n\t\traw.startTicks.length > 32 ||\n\t\t!(\"namespace\" in raw) ||\n\t\ttypeof raw.namespace !== \"string\" ||\n\t\t!/^pid:\\[\\d+\\]$/.test(raw.namespace) ||\n\t\t!(\"bootId\" in raw) ||\n\t\ttypeof raw.bootId !== \"string\" ||\n\t\t!/^[a-f0-9-]{36}$/.test(raw.bootId)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\treturn Object.freeze({ pid: raw.pid, startTicks: raw.startTicks, namespace: raw.namespace, bootId: raw.bootId });\n}\n\nfunction processStat(pid: number): { readonly startTicks: string; readonly state: string } {\n\tconst stat = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n\tconst fields = stat\n\t\t.slice(stat.lastIndexOf(\")\") + 2)\n\t\t.trim()\n\t\t.split(/\\s+/);\n\tconst startTicks = fields[19];\n\tconst state = fields[0];\n\tif (!startTicks || !/^\\d+$/.test(startTicks) || !state) throw new VerifiedRunError(\"process_identity\");\n\treturn { startTicks, state };\n}\n\nexport function captureNamespaceIdentity(pid: number): NamespaceIdentity {\n\tif (!Number.isSafeInteger(pid) || pid <= 0) throw new VerifiedRunError(\"process_identity\");\n\tconst before = processStat(pid);\n\tconst status = readFileSync(`/proc/${pid}/status`, \"utf8\");\n\tconst namespacePids = status\n\t\t.match(/^NSpid:\\s+(.+)$/m)?.[1]\n\t\t?.trim()\n\t\t.split(/\\s+/);\n\tif (!namespacePids || namespacePids.length < 2 || namespacePids.at(-1) !== \"1\")\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\tconst namespace = readlinkSync(`/proc/${pid}/ns/pid`);\n\tconst after = processStat(pid);\n\tif (before.startTicks !== after.startTicks || before.state === \"Z\" || after.state === \"Z\")\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\treturn parseNamespaceIdentity({ pid, startTicks: before.startTicks, namespace, bootId: readRunClock().bootId });\n}\n\n/** Read only. Never signal a PID that may have been reused by another process. */\nexport function probeNamespace(identity: NamespaceIdentity): \"alive\" | \"gone\" | \"unknown\" {\n\ttry {\n\t\tif (readRunClock().bootId !== identity.bootId) return \"unknown\";\n\t} catch {\n\t\treturn \"unknown\";\n\t}\n\ttry {\n\t\tconst current = processStat(identity.pid);\n\t\tif (current.startTicks !== identity.startTicks) return \"gone\";\n\t\t// Linux finishes PID namespace teardown before its init becomes a zombie.\n\t\tif (current.state === \"Z\" || current.state === \"X\") return \"gone\";\n\t\treturn readlinkSync(`/proc/${identity.pid}/ns/pid`) === identity.namespace ? \"alive\" : \"unknown\";\n\t} catch (error) {\n\t\tif (error instanceof Error && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ESRCH\"))\n\t\t\treturn \"gone\";\n\t\treturn \"unknown\";\n\t}\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SandboxOutcome } from "./broker.ts";
|
|
2
|
+
import type { VerifiedRunJournal } from "./journal.ts";
|
|
3
|
+
export interface OwnedRunCommand {
|
|
4
|
+
readonly role: "writer" | "verifier";
|
|
5
|
+
readonly argv: readonly string[];
|
|
6
|
+
readonly workspace: string;
|
|
7
|
+
readonly deadline: number;
|
|
8
|
+
readonly claimId: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface OwnedRunResult {
|
|
11
|
+
readonly executionId: string;
|
|
12
|
+
readonly result: SandboxOutcome;
|
|
13
|
+
readonly timeoutMs: number;
|
|
14
|
+
}
|
|
15
|
+
/** The mandatory durable intent boundary is shared by command and AgentSession writers. */
|
|
16
|
+
export declare function executeRunCommand(journal: VerifiedRunJournal, request: OwnedRunCommand, policy: {
|
|
17
|
+
readonly cleanupMs: number;
|
|
18
|
+
readonly maxOutputBytes: number;
|
|
19
|
+
readonly signal?: AbortSignal;
|
|
20
|
+
}): Promise<OwnedRunResult>;
|
|
21
|
+
//# sourceMappingURL=owned-execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-execution.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/owned-execution.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIvD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AACD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,2FAA2F;AAC3F,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE;IACP,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B,GACC,OAAO,CAAC,cAAc,CAAC,CAgCzB","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { performance } from \"node:perf_hooks\";\nimport { executeSandbox, type SandboxOutcome } from \"./broker.ts\";\nimport type { VerifiedRunJournal } from \"./journal.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport interface OwnedRunCommand {\n\treadonly role: \"writer\" | \"verifier\";\n\treadonly argv: readonly string[];\n\treadonly workspace: string;\n\treadonly deadline: number;\n\treadonly claimId: string | null;\n}\nexport interface OwnedRunResult {\n\treadonly executionId: string;\n\treadonly result: SandboxOutcome;\n\treadonly timeoutMs: number;\n}\n\n/** The mandatory durable intent boundary is shared by command and AgentSession writers. */\nexport async function executeRunCommand(\n\tjournal: VerifiedRunJournal,\n\trequest: OwnedRunCommand,\n\tpolicy: {\n\t\treadonly cleanupMs: number;\n\t\treadonly maxOutputBytes: number;\n\t\treadonly signal?: AbortSignal;\n\t},\n): Promise<OwnedRunResult> {\n\tif (Math.floor(request.deadline - performance.now()) <= 0) throw new VerifiedRunError(\"deadline\");\n\tif (policy.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst generation = journal.state.generation;\n\tconst executionId = randomUUID();\n\tjournal.append({ kind: \"dispatch\", executionId, role: request.role, claimId: request.claimId });\n\tconst timeoutMs = Math.floor(request.deadline - performance.now());\n\tif (timeoutMs <= 0 || policy.signal?.aborted) {\n\t\tconst failure = policy.signal?.aborted ? \"cancelled\" : \"deadline\";\n\t\tjournal.append({ kind: \"exited\", executionId, failure });\n\t\tthrow new VerifiedRunError(failure);\n\t}\n\tconst result = await executeSandbox({\n\t\tworkspace: request.workspace,\n\t\targv: request.argv,\n\t\twritable: request.role === \"writer\",\n\t\ttimeoutMs,\n\t\tcleanupMs: policy.cleanupMs,\n\t\tmaxOutputBytes: policy.maxOutputBytes,\n\t\t...(policy.signal ? { signal: policy.signal } : {}),\n\t\t...(journal.state.budget\n\t\t\t? {\n\t\t\t\t\tonReady: (identity: NamespaceIdentity) => {\n\t\t\t\t\t\tif (journal.state.generation !== generation) throw new VerifiedRunError(\"stale_generation\");\n\t\t\t\t\t\tjournal.append({ kind: \"process_ready\", executionId, identity });\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n\tif (journal.state.generation !== generation) throw new VerifiedRunError(\"stale_generation\");\n\tjournal.append({ kind: \"exited\", executionId, failure: request.role === \"writer\" ? result.failure : null });\n\treturn { executionId, result, timeoutMs };\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { executeSandbox } from "./broker.js";
|
|
4
|
+
import { VerifiedRunError } from "./storage.js";
|
|
5
|
+
/** The mandatory durable intent boundary is shared by command and AgentSession writers. */
|
|
6
|
+
export async function executeRunCommand(journal, request, policy) {
|
|
7
|
+
if (Math.floor(request.deadline - performance.now()) <= 0)
|
|
8
|
+
throw new VerifiedRunError("deadline");
|
|
9
|
+
if (policy.signal?.aborted)
|
|
10
|
+
throw new VerifiedRunError("cancelled");
|
|
11
|
+
const generation = journal.state.generation;
|
|
12
|
+
const executionId = randomUUID();
|
|
13
|
+
journal.append({ kind: "dispatch", executionId, role: request.role, claimId: request.claimId });
|
|
14
|
+
const timeoutMs = Math.floor(request.deadline - performance.now());
|
|
15
|
+
if (timeoutMs <= 0 || policy.signal?.aborted) {
|
|
16
|
+
const failure = policy.signal?.aborted ? "cancelled" : "deadline";
|
|
17
|
+
journal.append({ kind: "exited", executionId, failure });
|
|
18
|
+
throw new VerifiedRunError(failure);
|
|
19
|
+
}
|
|
20
|
+
const result = await executeSandbox({
|
|
21
|
+
workspace: request.workspace,
|
|
22
|
+
argv: request.argv,
|
|
23
|
+
writable: request.role === "writer",
|
|
24
|
+
timeoutMs,
|
|
25
|
+
cleanupMs: policy.cleanupMs,
|
|
26
|
+
maxOutputBytes: policy.maxOutputBytes,
|
|
27
|
+
...(policy.signal ? { signal: policy.signal } : {}),
|
|
28
|
+
...(journal.state.budget
|
|
29
|
+
? {
|
|
30
|
+
onReady: (identity) => {
|
|
31
|
+
if (journal.state.generation !== generation)
|
|
32
|
+
throw new VerifiedRunError("stale_generation");
|
|
33
|
+
journal.append({ kind: "process_ready", executionId, identity });
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
: {}),
|
|
37
|
+
});
|
|
38
|
+
if (journal.state.generation !== generation)
|
|
39
|
+
throw new VerifiedRunError("stale_generation");
|
|
40
|
+
journal.append({ kind: "exited", executionId, failure: request.role === "writer" ? result.failure : null });
|
|
41
|
+
return { executionId, result, timeoutMs };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=owned-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-execution.js","sourceRoot":"","sources":["../../../src/core/verified-run/owned-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { performance } from \"node:perf_hooks\";\nimport { executeSandbox, type SandboxOutcome } from \"./broker.ts\";\nimport type { VerifiedRunJournal } from \"./journal.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport interface OwnedRunCommand {\n\treadonly role: \"writer\" | \"verifier\";\n\treadonly argv: readonly string[];\n\treadonly workspace: string;\n\treadonly deadline: number;\n\treadonly claimId: string | null;\n}\nexport interface OwnedRunResult {\n\treadonly executionId: string;\n\treadonly result: SandboxOutcome;\n\treadonly timeoutMs: number;\n}\n\n/** The mandatory durable intent boundary is shared by command and AgentSession writers. */\nexport async function executeRunCommand(\n\tjournal: VerifiedRunJournal,\n\trequest: OwnedRunCommand,\n\tpolicy: {\n\t\treadonly cleanupMs: number;\n\t\treadonly maxOutputBytes: number;\n\t\treadonly signal?: AbortSignal;\n\t},\n): Promise<OwnedRunResult> {\n\tif (Math.floor(request.deadline - performance.now()) <= 0) throw new VerifiedRunError(\"deadline\");\n\tif (policy.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst generation = journal.state.generation;\n\tconst executionId = randomUUID();\n\tjournal.append({ kind: \"dispatch\", executionId, role: request.role, claimId: request.claimId });\n\tconst timeoutMs = Math.floor(request.deadline - performance.now());\n\tif (timeoutMs <= 0 || policy.signal?.aborted) {\n\t\tconst failure = policy.signal?.aborted ? \"cancelled\" : \"deadline\";\n\t\tjournal.append({ kind: \"exited\", executionId, failure });\n\t\tthrow new VerifiedRunError(failure);\n\t}\n\tconst result = await executeSandbox({\n\t\tworkspace: request.workspace,\n\t\targv: request.argv,\n\t\twritable: request.role === \"writer\",\n\t\ttimeoutMs,\n\t\tcleanupMs: policy.cleanupMs,\n\t\tmaxOutputBytes: policy.maxOutputBytes,\n\t\t...(policy.signal ? { signal: policy.signal } : {}),\n\t\t...(journal.state.budget\n\t\t\t? {\n\t\t\t\t\tonReady: (identity: NamespaceIdentity) => {\n\t\t\t\t\t\tif (journal.state.generation !== generation) throw new VerifiedRunError(\"stale_generation\");\n\t\t\t\t\t\tjournal.append({ kind: \"process_ready\", executionId, identity });\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n\tif (journal.state.generation !== generation) throw new VerifiedRunError(\"stale_generation\");\n\tjournal.append({ kind: \"exited\", executionId, failure: request.role === \"writer\" ? result.failure : null });\n\treturn { executionId, result, timeoutMs };\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RunContract } from "omk-protocol";
|
|
2
|
+
import type { VerifiedRunJournal } from "./journal.ts";
|
|
3
|
+
export interface RunPhaseContext {
|
|
4
|
+
readonly contract: RunContract;
|
|
5
|
+
readonly runPath: string;
|
|
6
|
+
readonly journal: VerifiedRunJournal;
|
|
7
|
+
readonly signal?: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=phase-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-context.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/phase-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B","sourcesContent":["import type { RunContract } from \"omk-protocol\";\nimport type { VerifiedRunJournal } from \"./journal.ts\";\n\nexport interface RunPhaseContext {\n\treadonly contract: RunContract;\n\treadonly runPath: string;\n\treadonly journal: VerifiedRunJournal;\n\treadonly signal?: AbortSignal;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-context.js","sourceRoot":"","sources":["../../../src/core/verified-run/phase-context.ts"],"names":[],"mappings":"","sourcesContent":["import type { RunContract } from \"omk-protocol\";\nimport type { VerifiedRunJournal } from \"./journal.ts\";\n\nexport interface RunPhaseContext {\n\treadonly contract: RunContract;\n\treadonly runPath: string;\n\treadonly journal: VerifiedRunJournal;\n\treadonly signal?: AbortSignal;\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type NamespaceIdentity } from "./namespace-identity.ts";
|
|
2
|
+
export declare const PROCESS_GATE_ARGV: readonly ["/bin/sh", "-c", "IFS= read -r gate && [ \"$gate\" = go ] && exec \"$@\"", "omk-process-gate"];
|
|
3
|
+
/** This JSON comes only from bwrap's private info FD, before any candidate code is released. */
|
|
4
|
+
export declare function identityFromSandboxInfo(bytes: string): NamespaceIdentity;
|
|
5
|
+
//# sourceMappingURL=process-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-gate.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/process-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG3F,eAAO,MAAM,iBAAiB,0GAKpB,CAAC;AAEX,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAoBxE","sourcesContent":["import { captureNamespaceIdentity, type NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport const PROCESS_GATE_ARGV = [\n\t\"/bin/sh\",\n\t\"-c\",\n\t'IFS= read -r gate && [ \"$gate\" = go ] && exec \"$@\"',\n\t\"omk-process-gate\",\n] as const;\n\n/** This JSON comes only from bwrap's private info FD, before any candidate code is released. */\nexport function identityFromSandboxInfo(bytes: string): NamespaceIdentity {\n\tlet info: unknown;\n\ttry {\n\t\tinfo = JSON.parse(bytes);\n\t} catch {\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\t}\n\tif (\n\t\ttypeof info !== \"object\" ||\n\t\tinfo === null ||\n\t\t!(\"child-pid\" in info) ||\n\t\ttypeof info[\"child-pid\"] !== \"number\" ||\n\t\t!(\"pid-namespace\" in info) ||\n\t\ttypeof info[\"pid-namespace\"] !== \"number\" ||\n\t\t!Number.isSafeInteger(info[\"pid-namespace\"])\n\t)\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\tconst identity = captureNamespaceIdentity(info[\"child-pid\"]);\n\tif (identity.namespace !== `pid:[${info[\"pid-namespace\"]}]`) throw new VerifiedRunError(\"process_identity\");\n\treturn identity;\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { captureNamespaceIdentity } from "./namespace-identity.js";
|
|
2
|
+
import { VerifiedRunError } from "./storage.js";
|
|
3
|
+
export const PROCESS_GATE_ARGV = [
|
|
4
|
+
"/bin/sh",
|
|
5
|
+
"-c",
|
|
6
|
+
'IFS= read -r gate && [ "$gate" = go ] && exec "$@"',
|
|
7
|
+
"omk-process-gate",
|
|
8
|
+
];
|
|
9
|
+
/** This JSON comes only from bwrap's private info FD, before any candidate code is released. */
|
|
10
|
+
export function identityFromSandboxInfo(bytes) {
|
|
11
|
+
let info;
|
|
12
|
+
try {
|
|
13
|
+
info = JSON.parse(bytes);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new VerifiedRunError("process_identity");
|
|
17
|
+
}
|
|
18
|
+
if (typeof info !== "object" ||
|
|
19
|
+
info === null ||
|
|
20
|
+
!("child-pid" in info) ||
|
|
21
|
+
typeof info["child-pid"] !== "number" ||
|
|
22
|
+
!("pid-namespace" in info) ||
|
|
23
|
+
typeof info["pid-namespace"] !== "number" ||
|
|
24
|
+
!Number.isSafeInteger(info["pid-namespace"]))
|
|
25
|
+
throw new VerifiedRunError("process_identity");
|
|
26
|
+
const identity = captureNamespaceIdentity(info["child-pid"]);
|
|
27
|
+
if (identity.namespace !== `pid:[${info["pid-namespace"]}]`)
|
|
28
|
+
throw new VerifiedRunError("process_identity");
|
|
29
|
+
return identity;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=process-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-gate.js","sourceRoot":"","sources":["../../../src/core/verified-run/process-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAA0B,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,SAAS;IACT,IAAI;IACJ,oDAAoD;IACpD,kBAAkB;CACT,CAAC;AAEX,gGAAgG;AAChG,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAqB;IACzE,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACJ,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC;IACD,IACC,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,QAAQ;QACrC,CAAC,CAAC,eAAe,IAAI,IAAI,CAAC;QAC1B,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,QAAQ;QACzC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAE5C,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,GAAG;QAAE,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IAC5G,OAAO,QAAQ,CAAC;AAAA,CAChB","sourcesContent":["import { captureNamespaceIdentity, type NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport const PROCESS_GATE_ARGV = [\n\t\"/bin/sh\",\n\t\"-c\",\n\t'IFS= read -r gate && [ \"$gate\" = go ] && exec \"$@\"',\n\t\"omk-process-gate\",\n] as const;\n\n/** This JSON comes only from bwrap's private info FD, before any candidate code is released. */\nexport function identityFromSandboxInfo(bytes: string): NamespaceIdentity {\n\tlet info: unknown;\n\ttry {\n\t\tinfo = JSON.parse(bytes);\n\t} catch {\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\t}\n\tif (\n\t\ttypeof info !== \"object\" ||\n\t\tinfo === null ||\n\t\t!(\"child-pid\" in info) ||\n\t\ttypeof info[\"child-pid\"] !== \"number\" ||\n\t\t!(\"pid-namespace\" in info) ||\n\t\ttypeof info[\"pid-namespace\"] !== \"number\" ||\n\t\t!Number.isSafeInteger(info[\"pid-namespace\"])\n\t)\n\t\tthrow new VerifiedRunError(\"process_identity\");\n\tconst identity = captureNamespaceIdentity(info[\"child-pid\"]);\n\tif (identity.namespace !== `pid:[${info[\"pid-namespace\"]}]`) throw new VerifiedRunError(\"process_identity\");\n\treturn identity;\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RunEvent, RunProjection } from "./run-types.ts";
|
|
2
|
+
/** Deterministic replay only. Recovery observations are supplied by the trusted host adapter. */
|
|
3
|
+
export declare function projectRun(events: readonly RunEvent[]): RunProjection;
|
|
4
|
+
//# sourceMappingURL=projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/projection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAmB,MAAM,gBAAgB,CAAC;AAI/E,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,aAAa,CAmOrE","sourcesContent":["import { reduceDagEvent } from \"./dag-projection.ts\";\nimport type { RunTaskProjection } from \"./dag-types.ts\";\nimport { reduceRecoveryEvent } from \"./recovery-projection.ts\";\nimport type { RunEvent, RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { acceptWriterDispatch, reduceWriterEvent } from \"./writer-projection.ts\";\n\n/** Deterministic replay only. Recovery observations are supplied by the trusted host adapter. */\nexport function projectRun(events: readonly RunEvent[]): RunProjection {\n\tconst first = events[0];\n\tif (first?.kind !== \"created\" || first.contract.runId !== first.command.runId)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst context: WriterReduction = {\n\t\tcontract: first.contract,\n\t\twriterFinished: false,\n\t\twriterStarted: false,\n\t\tproducerStarted: false,\n\t\twriterCommands: 0,\n\t\trequestBaseline: 0,\n\t\trequests: new Set(),\n\t\tstate: {\n\t\t\trunId: first.contract.runId,\n\t\t\trevision: 1,\n\t\t\tgeneration: 1,\n\t\t\texecution: \"ready\",\n\t\t\tsettlement: \"open\",\n\t\t\tverification: \"not_requested\",\n\t\t\tapplication: \"not_requested\",\n\t\t\tcandidateDigest: null,\n\t\t\tinputDigest: null,\n\t\t\treceiptDigest: null,\n\t\t\tfailure: null,\n\t\t\tactiveExecutionIds: [],\n\t\t\twriterOpen: false,\n\t\t\tmodelRequests: 0,\n\t\t\ttasks:\n\t\t\t\tfirst.contract.profile === \"linux-command-dag-v1\"\n\t\t\t\t\t? first.contract.writer.tasks.map(\n\t\t\t\t\t\t\t(task): RunTaskProjection => ({\n\t\t\t\t\t\t\t\ttaskId: task.id,\n\t\t\t\t\t\t\t\tattempt: 0,\n\t\t\t\t\t\t\t\tgeneration: 1,\n\t\t\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\t\t\tinputDigest: null,\n\t\t\t\t\t\t\t\toutputDigest: null,\n\t\t\t\t\t\t\t\tfailure: null,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t: [],\n\t\t\tbudget: null,\n\t\t\tenvironmentDigest: null,\n\t\t\tverificationDeadlineMs: null,\n\t\t\tlastClockMs: null,\n\t\t\tprocesses: [],\n\t\t},\n\t};\n\tconst dispatched = new Set<string>();\n\tconst checked = new Set<string>();\n\tconst commands = new Set([first.command.commandId]);\n\tlet activeRole: \"writer\" | \"verifier\" = \"writer\";\n\tfor (const event of events.slice(1)) {\n\t\tconst state = context.state;\n\t\tif (state.execution === \"failed\" || state.receiptDigest) throw new VerifiedRunError(\"integrity\");\n\t\tswitch (event.kind) {\n\t\t\tcase \"created\":\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\tcase \"budget_anchored\": {\n\t\t\t\tconst budget = event.budget;\n\t\t\t\tconst limits = first.contract.budget;\n\t\t\t\tif (\n\t\t\t\t\tstate.revision !== 1 ||\n\t\t\t\t\tstate.budget ||\n\t\t\t\t\tbudget.workDeadlineMs - budget.startedMs !== limits.workMs ||\n\t\t\t\t\tbudget.verifyCapMs - budget.workDeadlineMs !== limits.verifyMs ||\n\t\t\t\t\tbudget.cleanupDeadlineMs - budget.verifyCapMs !== limits.cleanupMs\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\tbudget,\n\t\t\t\t\tenvironmentDigest: event.environmentDigest,\n\t\t\t\t\tlastClockMs: budget.startedMs,\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"input_checkpoint\":\n\t\t\t\tif (\n\t\t\t\t\tstate.revision !== 2 ||\n\t\t\t\t\t!state.budget ||\n\t\t\t\t\tstate.inputDigest ||\n\t\t\t\t\tevent.digest !== first.contract.workspace.baseDigest\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tcontext.state = { ...state, inputDigest: event.digest };\n\t\t\t\tbreak;\n\t\t\tcase \"task_started\":\n\t\t\tcase \"task_finished\":\n\t\t\tcase \"tasks_paused\":\n\t\t\t\treduceDagEvent(context, event);\n\t\t\t\tbreak;\n\t\t\tcase \"writer_opened\":\n\t\t\tcase \"model_request\":\n\t\t\tcase \"writer_closed\":\n\t\t\t\treduceWriterEvent(context, event);\n\t\t\t\tbreak;\n\t\t\tcase \"dispatch\": {\n\t\t\t\tif (state.failure || state.activeExecutionIds.length || dispatched.has(event.executionId))\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tif (event.role === \"writer\") {\n\t\t\t\t\tacceptWriterDispatch(context, event);\n\t\t\t\t} else {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!context.writerFinished ||\n\t\t\t\t\t\tstate.writerOpen ||\n\t\t\t\t\t\t!state.candidateDigest ||\n\t\t\t\t\t\tevent.claimId === null ||\n\t\t\t\t\t\t!first.contract.checks.some((check) => check.claimId === event.claimId) ||\n\t\t\t\t\t\tchecked.has(event.claimId)\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\t\tchecked.add(event.claimId);\n\t\t\t\t}\n\t\t\t\tdispatched.add(event.executionId);\n\t\t\t\tactiveRole = event.role;\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\texecution: \"running\",\n\t\t\t\t\tsettlement: \"draining\",\n\t\t\t\t\tactiveExecutionIds: [event.executionId],\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"process_ready\":\n\t\t\t\tif (\n\t\t\t\t\t!state.budget ||\n\t\t\t\t\tstate.activeExecutionIds[0] !== event.executionId ||\n\t\t\t\t\tevent.identity.bootId !== state.budget.bootId ||\n\t\t\t\t\tstate.processes.some((item) => item.executionId === event.executionId)\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\tprocesses: [...state.processes, { executionId: event.executionId, identity: event.identity }],\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"exited\":\n\t\t\t\tif (\n\t\t\t\t\tstate.activeExecutionIds[0] !== event.executionId ||\n\t\t\t\t\t(state.budget &&\n\t\t\t\t\t\tevent.failure === null &&\n\t\t\t\t\t\t!state.processes.some((item) => item.executionId === event.executionId))\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tif (activeRole === \"writer\") context.writerFinished = event.failure === null;\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\tsettlement: state.writerOpen ? \"open\" : \"settled\",\n\t\t\t\t\tactiveExecutionIds: [],\n\t\t\t\t\tfailure: event.failure,\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"candidate\": {\n\t\t\t\tif (\n\t\t\t\t\t!context.writerFinished ||\n\t\t\t\t\tstate.writerOpen ||\n\t\t\t\t\tstate.failure ||\n\t\t\t\t\tstate.activeExecutionIds.length ||\n\t\t\t\t\tstate.candidateDigest ||\n\t\t\t\t\tstate.tasks.some((task) => task.status !== \"succeeded\" || task.generation !== state.generation)\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tif (state.budget) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tevent.observedMs === undefined ||\n\t\t\t\t\t\tevent.verificationDeadlineMs === undefined ||\n\t\t\t\t\t\tevent.observedMs < state.budget.startedMs ||\n\t\t\t\t\t\tevent.observedMs > state.budget.workDeadlineMs ||\n\t\t\t\t\t\tevent.verificationDeadlineMs !==\n\t\t\t\t\t\t\tMath.min(event.observedMs + first.contract.budget.verifyMs, state.budget.verifyCapMs)\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\t} else if (event.observedMs !== undefined || event.verificationDeadlineMs !== undefined)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\tcandidateDigest: event.digest,\n\t\t\t\t\tverificationDeadlineMs: event.verificationDeadlineMs ?? null,\n\t\t\t\t\tlastClockMs: event.observedMs ?? null,\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"resumed\":\n\t\t\tcase \"tasks_retried\":\n\t\t\tcase \"writer_restarted\":\n\t\t\t\treduceRecoveryEvent(context, event, { commands, checked, activeRole });\n\t\t\t\tbreak;\n\t\t\tcase \"evaluated\":\n\t\t\t\tif (\n\t\t\t\t\t!state.candidateDigest ||\n\t\t\t\t\tstate.writerOpen ||\n\t\t\t\t\tstate.activeExecutionIds.length ||\n\t\t\t\t\tchecked.size !== first.contract.checks.length ||\n\t\t\t\t\t(event.verified && state.failure)\n\t\t\t\t)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\treceiptDigest: event.receiptDigest,\n\t\t\t\t\texecution: \"succeeded\",\n\t\t\t\t\tverification: event.verified ? \"verified\" : \"violated\",\n\t\t\t\t\tapplication: event.verified ? \"candidate_ready\" : \"not_requested\",\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"failed\":\n\t\t\t\tcontext.state = {\n\t\t\t\t\t...state,\n\t\t\t\t\texecution: \"failed\",\n\t\t\t\t\tfailure: event.code,\n\t\t\t\t\tverification: \"inconclusive\",\n\t\t\t\t\tsettlement: state.activeExecutionIds.length || state.writerOpen ? \"quarantined\" : \"settled\",\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tconst exhaustive: never = event;\n\t\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t\t}\n\t\t}\n\t\tcontext.state = { ...context.state, revision: state.revision + 1 };\n\t}\n\treturn Object.freeze({\n\t\t...context.state,\n\t\tactiveExecutionIds: Object.freeze([...context.state.activeExecutionIds]),\n\t\tprocesses: Object.freeze(context.state.processes.map((item) => Object.freeze(item))),\n\t\ttasks: Object.freeze(context.state.tasks.map((task) => Object.freeze(task))),\n\t});\n}\n"]}
|