open-multi-agent-kit 1.2.0 → 1.2.3
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 +54 -0
- package/README.md +2 -2
- package/dist/approval-api.d.ts +5 -0
- package/dist/approval-api.d.ts.map +1 -0
- package/dist/approval-api.js +5 -0
- package/dist/approval-api.js.map +1 -0
- package/dist/cli/session-picker.d.ts +2 -2
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/commands/verified-run-cli.d.ts.map +1 -1
- package/dist/commands/verified-run-cli.js +69 -22
- package/dist/commands/verified-run-cli.js.map +1 -1
- package/dist/commands/verified-run-signal.d.ts +3 -0
- package/dist/commands/verified-run-signal.d.ts.map +1 -0
- package/dist/commands/verified-run-signal.js +15 -0
- package/dist/commands/verified-run-signal.js.map +1 -0
- package/dist/coordination/broker.d.ts.map +1 -1
- package/dist/coordination/broker.js +13 -6
- package/dist/coordination/broker.js.map +1 -1
- package/dist/coordination/operation.d.ts +1 -0
- package/dist/coordination/operation.d.ts.map +1 -1
- package/dist/coordination/operation.js +55 -3
- package/dist/coordination/operation.js.map +1 -1
- package/dist/coordination/resource.d.ts +1 -1
- package/dist/coordination/resource.d.ts.map +1 -1
- package/dist/coordination/resource.js +10 -4
- package/dist/coordination/resource.js.map +1 -1
- package/dist/coordination/types.d.ts.map +1 -1
- package/dist/coordination/types.js +1 -1
- package/dist/coordination/types.js.map +1 -1
- package/dist/core/adaptorch-bridge.d.ts +1 -1
- package/dist/core/adaptorch-bridge.d.ts.map +1 -1
- package/dist/core/adaptorch-bridge.js +1 -1
- package/dist/core/adaptorch-bridge.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -16
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +32 -33
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +20 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +7 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +14 -29
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/fallback.d.ts +16 -5
- package/dist/core/compaction/fallback.d.ts.map +1 -1
- package/dist/core/compaction/fallback.js +4 -3
- package/dist/core/compaction/fallback.js.map +1 -1
- package/dist/core/compaction/model-failover.d.ts +21 -0
- package/dist/core/compaction/model-failover.d.ts.map +1 -0
- package/dist/core/compaction/model-failover.js +46 -0
- package/dist/core/compaction/model-failover.js.map +1 -0
- package/dist/core/compaction/session-summary.d.ts +21 -0
- package/dist/core/compaction/session-summary.d.ts.map +1 -0
- package/dist/core/compaction/session-summary.js +27 -0
- package/dist/core/compaction/session-summary.js.map +1 -0
- package/dist/core/export-html/template.js +14 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/session-lifecycle-types.d.ts +14 -0
- package/dist/core/extensions/session-lifecycle-types.d.ts.map +1 -0
- package/dist/core/extensions/session-lifecycle-types.js +2 -0
- package/dist/core/extensions/session-lifecycle-types.js.map +1 -0
- package/dist/core/extensions/types.d.ts +4 -9
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +10 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/legacy-resource-policy.d.ts +7 -0
- package/dist/core/legacy-resource-policy.d.ts.map +1 -0
- package/dist/core/legacy-resource-policy.js +9 -0
- package/dist/core/legacy-resource-policy.js.map +1 -0
- package/dist/core/mcp/config.d.ts.map +1 -1
- package/dist/core/mcp/config.js +17 -3
- package/dist/core/mcp/config.js.map +1 -1
- package/dist/core/mcp/connection-queue.d.ts +12 -0
- package/dist/core/mcp/connection-queue.d.ts.map +1 -0
- package/dist/core/mcp/connection-queue.js +46 -0
- package/dist/core/mcp/connection-queue.js.map +1 -0
- package/dist/core/mcp/manager-runtime.d.ts +55 -0
- package/dist/core/mcp/manager-runtime.d.ts.map +1 -0
- package/dist/core/mcp/manager-runtime.js +66 -0
- package/dist/core/mcp/manager-runtime.js.map +1 -0
- package/dist/core/mcp/manager.d.ts +12 -68
- package/dist/core/mcp/manager.d.ts.map +1 -1
- package/dist/core/mcp/manager.js +33 -113
- package/dist/core/mcp/manager.js.map +1 -1
- package/dist/core/mcp/protocol.d.ts.map +1 -1
- package/dist/core/mcp/protocol.js +70 -40
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +59 -129
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-patterns.d.ts +7 -0
- package/dist/core/package-resource-patterns.d.ts.map +1 -0
- package/dist/core/package-resource-patterns.js +99 -0
- package/dist/core/package-resource-patterns.js.map +1 -0
- package/dist/core/provider-resilience.d.ts +9 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +15 -0
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts +5 -2
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -8
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-execution-api.d.ts +8 -1
- package/dist/core/run-execution-api.d.ts.map +1 -1
- package/dist/core/run-execution-api.js +4 -0
- package/dist/core/run-execution-api.js.map +1 -1
- package/dist/core/run-journal.d.ts +1 -2
- package/dist/core/run-journal.d.ts.map +1 -1
- package/dist/core/run-journal.js +2 -19
- package/dist/core/run-journal.js.map +1 -1
- package/dist/core/session-listing.d.ts +51 -0
- package/dist/core/session-listing.d.ts.map +1 -0
- package/dist/core/session-listing.js +111 -0
- package/dist/core/session-listing.js.map +1 -0
- package/dist/core/session-manager.d.ts +12 -37
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -118
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-message-text.d.ts +5 -0
- package/dist/core/session-message-text.d.ts.map +1 -0
- package/dist/core/session-message-text.js +9 -0
- package/dist/core/session-message-text.js.map +1 -0
- package/dist/core/skills-catalog-cache.d.ts +2 -0
- package/dist/core/skills-catalog-cache.d.ts.map +1 -1
- package/dist/core/skills-catalog-cache.js +71 -17
- package/dist/core/skills-catalog-cache.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/verified-run/authority-clock.d.ts +3 -0
- package/dist/core/verified-run/authority-clock.d.ts.map +1 -0
- package/dist/core/verified-run/authority-clock.js +25 -0
- package/dist/core/verified-run/authority-clock.js.map +1 -0
- package/dist/core/verified-run/authority-errors.d.ts +10 -0
- package/dist/core/verified-run/authority-errors.d.ts.map +1 -0
- package/dist/core/verified-run/authority-errors.js +17 -0
- package/dist/core/verified-run/authority-errors.js.map +1 -0
- package/dist/core/verified-run/authority-events.d.ts +126 -0
- package/dist/core/verified-run/authority-events.d.ts.map +1 -0
- package/dist/core/verified-run/authority-events.js +482 -0
- package/dist/core/verified-run/authority-events.js.map +1 -0
- package/dist/core/verified-run/authority-journal.d.ts +27 -0
- package/dist/core/verified-run/authority-journal.d.ts.map +1 -0
- package/dist/core/verified-run/authority-journal.js +83 -0
- package/dist/core/verified-run/authority-journal.js.map +1 -0
- package/dist/core/verified-run/authority-meaning.d.ts +13 -0
- package/dist/core/verified-run/authority-meaning.d.ts.map +1 -0
- package/dist/core/verified-run/authority-meaning.js +40 -0
- package/dist/core/verified-run/authority-meaning.js.map +1 -0
- package/dist/core/verified-run/authority-runtime.d.ts +82 -0
- package/dist/core/verified-run/authority-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/authority-runtime.js +169 -0
- package/dist/core/verified-run/authority-runtime.js.map +1 -0
- package/dist/core/verified-run/authority-store.d.ts +204 -0
- package/dist/core/verified-run/authority-store.d.ts.map +1 -0
- package/dist/core/verified-run/authority-store.js +852 -0
- package/dist/core/verified-run/authority-store.js.map +1 -0
- package/dist/core/verified-run/broker.d.ts +8 -1
- package/dist/core/verified-run/broker.d.ts.map +1 -1
- package/dist/core/verified-run/broker.js +94 -90
- package/dist/core/verified-run/broker.js.map +1 -1
- package/dist/core/verified-run/candidate-policy.d.ts +10 -0
- package/dist/core/verified-run/candidate-policy.d.ts.map +1 -0
- package/dist/core/verified-run/candidate-policy.js +33 -0
- package/dist/core/verified-run/candidate-policy.js.map +1 -0
- package/dist/core/verified-run/candidate.d.ts.map +1 -1
- package/dist/core/verified-run/candidate.js +5 -10
- package/dist/core/verified-run/candidate.js.map +1 -1
- package/dist/core/verified-run/coordinator.d.ts +35 -17
- package/dist/core/verified-run/coordinator.d.ts.map +1 -1
- package/dist/core/verified-run/coordinator.js +111 -57
- package/dist/core/verified-run/coordinator.js.map +1 -1
- package/dist/core/verified-run/dag-phase.d.ts.map +1 -1
- package/dist/core/verified-run/dag-phase.js +1 -1
- package/dist/core/verified-run/dag-phase.js.map +1 -1
- package/dist/core/verified-run/dag-recovery.d.ts +5 -1
- package/dist/core/verified-run/dag-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/dag-recovery.js +10 -4
- package/dist/core/verified-run/dag-recovery.js.map +1 -1
- package/dist/core/verified-run/event-parser.d.ts.map +1 -1
- package/dist/core/verified-run/event-parser.js +33 -0
- package/dist/core/verified-run/event-parser.js.map +1 -1
- package/dist/core/verified-run/evidence-read-projection.d.ts +4 -0
- package/dist/core/verified-run/evidence-read-projection.d.ts.map +1 -0
- package/dist/core/verified-run/evidence-read-projection.js +27 -0
- package/dist/core/verified-run/evidence-read-projection.js.map +1 -0
- package/dist/core/verified-run/evidence.d.ts +12 -1
- package/dist/core/verified-run/evidence.d.ts.map +1 -1
- package/dist/core/verified-run/evidence.js +51 -2
- package/dist/core/verified-run/evidence.js.map +1 -1
- package/dist/core/verified-run/git-candidate-preflight.d.ts +4 -0
- package/dist/core/verified-run/git-candidate-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/git-candidate-preflight.js +34 -0
- package/dist/core/verified-run/git-candidate-preflight.js.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts +24 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.js +174 -0
- package/dist/core/verified-run/git-effect-supervisor.js.map +1 -0
- package/dist/core/verified-run/git-execution.d.ts +27 -0
- package/dist/core/verified-run/git-execution.d.ts.map +1 -0
- package/dist/core/verified-run/git-execution.js +118 -0
- package/dist/core/verified-run/git-execution.js.map +1 -0
- package/dist/core/verified-run/git-plumbing.d.ts +37 -0
- package/dist/core/verified-run/git-plumbing.d.ts.map +1 -0
- package/dist/core/verified-run/git-plumbing.js +171 -0
- package/dist/core/verified-run/git-plumbing.js.map +1 -0
- package/dist/core/verified-run/git-publication-worker.d.ts +2 -0
- package/dist/core/verified-run/git-publication-worker.d.ts.map +1 -0
- package/dist/core/verified-run/git-publication-worker.js +54 -0
- package/dist/core/verified-run/git-publication-worker.js.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts +4 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.js +29 -0
- package/dist/core/verified-run/git-sandbox-layout.js.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts +19 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.js +109 -0
- package/dist/core/verified-run/git-worker-protocol.js.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts +19 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.js +74 -0
- package/dist/core/verified-run/git-worker-runtime.js.map +1 -0
- package/dist/core/verified-run/journal.d.ts +2 -3
- package/dist/core/verified-run/journal.d.ts.map +1 -1
- package/dist/core/verified-run/journal.js.map +1 -1
- package/dist/core/verified-run/namespace-identity.d.ts.map +1 -1
- package/dist/core/verified-run/namespace-identity.js +1 -1
- package/dist/core/verified-run/namespace-identity.js.map +1 -1
- package/dist/core/verified-run/owned-execution.d.ts +10 -1
- package/dist/core/verified-run/owned-execution.d.ts.map +1 -1
- package/dist/core/verified-run/owned-execution.js +124 -31
- package/dist/core/verified-run/owned-execution.js.map +1 -1
- package/dist/core/verified-run/phase-context.d.ts +2 -0
- package/dist/core/verified-run/phase-context.d.ts.map +1 -1
- package/dist/core/verified-run/phase-context.js.map +1 -1
- package/dist/core/verified-run/projection.d.ts.map +1 -1
- package/dist/core/verified-run/projection.js +51 -1
- package/dist/core/verified-run/projection.js.map +1 -1
- package/dist/core/verified-run/publish-preflight.d.ts +12 -0
- package/dist/core/verified-run/publish-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/publish-preflight.js +38 -0
- package/dist/core/verified-run/publish-preflight.js.map +1 -0
- package/dist/core/verified-run/publish-start.d.ts +5 -0
- package/dist/core/verified-run/publish-start.d.ts.map +1 -0
- package/dist/core/verified-run/publish-start.js +7 -0
- package/dist/core/verified-run/publish-start.js.map +1 -0
- package/dist/core/verified-run/recovery-projection.d.ts.map +1 -1
- package/dist/core/verified-run/recovery-projection.js +5 -0
- package/dist/core/verified-run/recovery-projection.js.map +1 -1
- package/dist/core/verified-run/recovery.d.ts +5 -1
- package/dist/core/verified-run/recovery.d.ts.map +1 -1
- package/dist/core/verified-run/recovery.js +10 -4
- package/dist/core/verified-run/recovery.js.map +1 -1
- package/dist/core/verified-run/run-plan.d.ts +17 -0
- package/dist/core/verified-run/run-plan.d.ts.map +1 -0
- package/dist/core/verified-run/run-plan.js +18 -0
- package/dist/core/verified-run/run-plan.js.map +1 -0
- package/dist/core/verified-run/run-publish-owned.d.ts +6 -0
- package/dist/core/verified-run/run-publish-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish-owned.js +199 -0
- package/dist/core/verified-run/run-publish-owned.js.map +1 -0
- package/dist/core/verified-run/run-publish.d.ts +19 -0
- package/dist/core/verified-run/run-publish.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish.js +210 -0
- package/dist/core/verified-run/run-publish.js.map +1 -0
- package/dist/core/verified-run/run-status-owned.d.ts +4 -0
- package/dist/core/verified-run/run-status-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-status-owned.js +14 -0
- package/dist/core/verified-run/run-status-owned.js.map +1 -0
- package/dist/core/verified-run/run-status.d.ts +133 -0
- package/dist/core/verified-run/run-status.d.ts.map +1 -0
- package/dist/core/verified-run/run-status.js +193 -0
- package/dist/core/verified-run/run-status.js.map +1 -0
- package/dist/core/verified-run/run-types.d.ts +31 -0
- package/dist/core/verified-run/run-types.d.ts.map +1 -1
- package/dist/core/verified-run/run-types.js.map +1 -1
- package/dist/core/verified-run/storage.d.ts.map +1 -1
- package/dist/core/verified-run/storage.js +1 -1
- package/dist/core/verified-run/storage.js.map +1 -1
- package/dist/core/verified-run/supervisor-adapter.d.ts +81 -0
- package/dist/core/verified-run/supervisor-adapter.d.ts.map +1 -0
- package/dist/core/verified-run/supervisor-adapter.js +168 -0
- package/dist/core/verified-run/supervisor-adapter.js.map +1 -0
- package/dist/core/verified-run/verification-phase.d.ts.map +1 -1
- package/dist/core/verified-run/verification-phase.js +1 -1
- package/dist/core/verified-run/verification-phase.js.map +1 -1
- package/dist/core/verified-run/writer-phase.d.ts.map +1 -1
- package/dist/core/verified-run/writer-phase.js +1 -0
- package/dist/core/verified-run/writer-phase.js.map +1 -1
- package/dist/core/verified-run/writer-recovery.d.ts +2 -0
- package/dist/core/verified-run/writer-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/writer-recovery.js +1 -0
- package/dist/core/verified-run/writer-recovery.js.map +1 -1
- package/dist/core/workload-shard-execution-types.d.ts +4 -1
- package/dist/core/workload-shard-execution-types.d.ts.map +1 -1
- package/dist/core/workload-shard-execution-types.js.map +1 -1
- package/dist/core/workload-shard-executor.d.ts +2 -2
- package/dist/core/workload-shard-executor.d.ts.map +1 -1
- package/dist/core/workload-shard-executor.js +16 -37
- package/dist/core/workload-shard-executor.js.map +1 -1
- package/dist/core/workload-shard-frontier.d.ts +5 -0
- package/dist/core/workload-shard-frontier.d.ts.map +1 -0
- package/dist/core/workload-shard-frontier.js +47 -0
- package/dist/core/workload-shard-frontier.js.map +1 -0
- package/dist/core/workload-shard-runner.d.ts.map +1 -1
- package/dist/core/workload-shard-runner.js +28 -17
- package/dist/core/workload-shard-runner.js.map +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/metacognition/bridge-result.d.ts +148 -0
- package/dist/metacognition/bridge-result.d.ts.map +1 -0
- package/dist/metacognition/bridge-result.js +46 -0
- package/dist/metacognition/bridge-result.js.map +1 -0
- package/dist/metacognition/calibration-selective.d.ts.map +1 -1
- package/dist/metacognition/calibration-selective.js +8 -2
- package/dist/metacognition/calibration-selective.js.map +1 -1
- package/dist/metacognition/index.d.ts +1 -0
- package/dist/metacognition/index.d.ts.map +1 -1
- package/dist/metacognition/index.js +1 -0
- package/dist/metacognition/index.js.map +1 -1
- package/dist/metacognition/risk.d.ts.map +1 -1
- package/dist/metacognition/risk.js +28 -14
- package/dist/metacognition/risk.js.map +1 -1
- package/dist/metacognition/runtime-bridge.d.ts +41 -14
- package/dist/metacognition/runtime-bridge.d.ts.map +1 -1
- package/dist/metacognition/runtime-bridge.js +357 -39
- package/dist/metacognition/runtime-bridge.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +42 -26
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-container.d.ts +7 -0
- package/dist/modes/interactive/components/chat-container.d.ts.map +1 -0
- package/dist/modes/interactive/components/chat-container.js +14 -0
- package/dist/modes/interactive/components/chat-container.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +4 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +0 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-async-search.d.ts +33 -0
- package/dist/modes/interactive/components/session-selector-async-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-async-search.js +109 -0
- package/dist/modes/interactive/components/session-selector-async-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts +6 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.js +9 -0
- package/dist/modes/interactive/components/session-selector-loaders.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-tree.d.ts +16 -0
- package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-tree.js +46 -0
- package/dist/modes/interactive/components/session-selector-tree.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +6 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +36 -76
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution-images.d.ts +32 -0
- package/dist/modes/interactive/components/tool-execution-images.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution-images.js +144 -0
- package/dist/modes/interactive/components/tool-execution-images.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -4
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -71
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.d.ts +8 -4
- package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.js +35 -1
- package/dist/modes/interactive/tui-diagnostics.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -17
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-response.d.ts +5 -0
- package/dist/modes/rpc/rpc-response.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-response.js +17 -0
- package/dist/modes/rpc/rpc-response.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +3 -5
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/adaptorch-preview-spec.md +7 -7
- package/docs/atomic-commit-planning.md +69 -0
- package/docs/compaction.md +26 -1
- package/docs/extensions.md +14 -0
- package/docs/mcp.md +22 -0
- package/docs/metacognition.md +79 -0
- package/docs/model-catalog-refresh.md +159 -1
- package/docs/models.md +1 -1
- package/docs/runtime-algorithms.md +49 -4
- package/docs/session-format.md +8 -0
- package/docs/sessions.md +19 -0
- package/docs/skills.md +19 -0
- package/docs/terminal-setup.md +15 -0
- package/docs/tui.md +41 -0
- package/docs/verified-run-safety.md +75 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- 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/doom-overlay/wad-finder.ts +7 -3
- 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 -8
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { MAX_VERIFIED_RUN_GENERATIONS } from "omk-protocol";
|
|
2
|
+
import { SETTLED_EFFECT_STATES } from "../../coordination/types.js";
|
|
3
|
+
import { authorityPendingReconcile } from "./authority-events.js";
|
|
4
|
+
/** Derive the status view; pure projection truth in, status out, no I/O. */
|
|
5
|
+
export function deriveRunStatus(state) {
|
|
6
|
+
const unresolved = [];
|
|
7
|
+
if (state.activeExecutionIds.length > 0 || state.writerOpen)
|
|
8
|
+
unresolved.push("pending_effects");
|
|
9
|
+
if (state.candidateDigest && !state.receiptDigest && state.execution !== "failed" && state.execution !== "ready")
|
|
10
|
+
unresolved.push("verification_pending");
|
|
11
|
+
if (state.verification === "violated")
|
|
12
|
+
unresolved.push("verification_violated");
|
|
13
|
+
if (state.publication === "intent")
|
|
14
|
+
unresolved.push("publication_intent");
|
|
15
|
+
if (state.publication === "failed")
|
|
16
|
+
unresolved.push("publication_refused");
|
|
17
|
+
if (state.publication === "reconciliation_required")
|
|
18
|
+
unresolved.push("publication_reconciliation_required");
|
|
19
|
+
const completion = state.publication === "accepted"
|
|
20
|
+
? "published"
|
|
21
|
+
: state.verification === "verified"
|
|
22
|
+
? "verification_passed"
|
|
23
|
+
: state.candidateDigest
|
|
24
|
+
? "prompt_settled"
|
|
25
|
+
: "none";
|
|
26
|
+
const terminal = state.execution === "succeeded" || state.execution === "failed";
|
|
27
|
+
let lifecycle;
|
|
28
|
+
if (state.settlement === "quarantined")
|
|
29
|
+
lifecycle = "quarantined";
|
|
30
|
+
else if (state.execution === "ready")
|
|
31
|
+
lifecycle = "queued";
|
|
32
|
+
else if (state.execution === "running") {
|
|
33
|
+
if (state.lastRecovery && state.lastRecovery.generation === state.generation)
|
|
34
|
+
lifecycle = "resuming";
|
|
35
|
+
else if (state.candidateDigest && !state.receiptDigest)
|
|
36
|
+
lifecycle = "verifying";
|
|
37
|
+
else
|
|
38
|
+
lifecycle = "running";
|
|
39
|
+
}
|
|
40
|
+
else if (state.execution === "paused")
|
|
41
|
+
lifecycle = "blocked";
|
|
42
|
+
else if (state.execution === "failed")
|
|
43
|
+
lifecycle = state.failure === "cancelled" ? "cancelled" : "failed";
|
|
44
|
+
else if (state.verification === "verified")
|
|
45
|
+
lifecycle = state.publication === "accepted" ? "published" : "accepted";
|
|
46
|
+
else
|
|
47
|
+
lifecycle = "violated";
|
|
48
|
+
return Object.freeze({
|
|
49
|
+
runId: state.runId,
|
|
50
|
+
revision: state.revision,
|
|
51
|
+
generation: state.generation,
|
|
52
|
+
lifecycle,
|
|
53
|
+
completion,
|
|
54
|
+
// Clean success means the verification ladder actually climbed: a
|
|
55
|
+
// terminal cancel/failure/violation, or a verified run with an open
|
|
56
|
+
// publish outbox, never reports clean.
|
|
57
|
+
cleanSuccess: terminal && unresolved.length === 0 && (completion === "verification_passed" || completion === "published"),
|
|
58
|
+
terminal,
|
|
59
|
+
unresolved: Object.freeze(unresolved),
|
|
60
|
+
execution: state.execution,
|
|
61
|
+
settlement: state.settlement,
|
|
62
|
+
verification: state.verification,
|
|
63
|
+
application: state.application,
|
|
64
|
+
publication: Object.freeze({
|
|
65
|
+
state: state.publication,
|
|
66
|
+
commandId: state.publicationCommandId,
|
|
67
|
+
candidateOid: state.publicationCandidateOid,
|
|
68
|
+
ref: state.publicationRef,
|
|
69
|
+
failure: state.publicationFailure,
|
|
70
|
+
}),
|
|
71
|
+
cause: state.failure,
|
|
72
|
+
pendingEffects: state.activeExecutionIds.length,
|
|
73
|
+
writerOpen: state.writerOpen,
|
|
74
|
+
recovery: state.lastRecovery,
|
|
75
|
+
recoveryCommands: Object.freeze(recoveryCommands(state)),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function recoveryCommands(state) {
|
|
79
|
+
const commands = [];
|
|
80
|
+
if (state.generation >= MAX_VERIFIED_RUN_GENERATIONS)
|
|
81
|
+
return commands;
|
|
82
|
+
const base = { runId: state.runId, revision: state.revision, generation: state.generation };
|
|
83
|
+
// A frozen candidate can be re-verified under a new generation (resume gate
|
|
84
|
+
// mirrors `assertCandidateRecoverable`: candidate, no receipt, not failed).
|
|
85
|
+
if (state.candidateDigest &&
|
|
86
|
+
!state.receiptDigest &&
|
|
87
|
+
!state.writerOpen &&
|
|
88
|
+
state.execution !== "failed" &&
|
|
89
|
+
state.execution !== "ready") {
|
|
90
|
+
commands.push({
|
|
91
|
+
...base,
|
|
92
|
+
command: "resume",
|
|
93
|
+
scope: { candidateDigest: state.candidateDigest },
|
|
94
|
+
advisory: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// DAG tasks can be retried from the input checkpoint (retry gate mirrors
|
|
98
|
+
// `commandDisposition`: input checkpoint present, tasks exist).
|
|
99
|
+
if (state.inputDigest && state.tasks.length > 0) {
|
|
100
|
+
const failed = state.tasks
|
|
101
|
+
.filter((task) => task.status === "failed" || (task.status === "pending" && task.attempt > 0))
|
|
102
|
+
.map((task) => task.taskId);
|
|
103
|
+
if (failed.length > 0) {
|
|
104
|
+
commands.push({
|
|
105
|
+
...base,
|
|
106
|
+
command: "retry_tasks",
|
|
107
|
+
scope: { baseDigest: state.inputDigest, taskIds: Object.freeze(failed) },
|
|
108
|
+
advisory: true,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// A writer that never produced a candidate restarts from the input
|
|
113
|
+
// checkpoint (non-DAG profiles only; DAG recovery is retry_tasks).
|
|
114
|
+
if (state.inputDigest && !state.candidateDigest && state.tasks.length === 0 && state.execution !== "ready") {
|
|
115
|
+
commands.push({
|
|
116
|
+
...base,
|
|
117
|
+
command: "restart_writer",
|
|
118
|
+
scope: { baseDigest: state.inputDigest },
|
|
119
|
+
advisory: true,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// The publish outbox: a verified, settled run can publish; a refused or
|
|
123
|
+
// half-published intent is re-driven by the same command identity.
|
|
124
|
+
if (state.application === "candidate_ready" &&
|
|
125
|
+
state.settlement === "settled" &&
|
|
126
|
+
state.receiptDigest &&
|
|
127
|
+
state.candidateDigest &&
|
|
128
|
+
(state.publication === "none" || state.publication === "failed" || state.publication === "intent")) {
|
|
129
|
+
commands.push({
|
|
130
|
+
...base,
|
|
131
|
+
command: "publish",
|
|
132
|
+
scope: { candidateDigest: state.candidateDigest },
|
|
133
|
+
advisory: true,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return commands;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Derive the authority status from the committed projection; pass the journal
|
|
140
|
+
* records' events so quarantine/cancel causes stay distinguishable — the
|
|
141
|
+
* projection alone intentionally does not restate them.
|
|
142
|
+
*/
|
|
143
|
+
export function deriveAuthorityStatus(projection, events = []) {
|
|
144
|
+
const transitionOf = (grantSequence) => {
|
|
145
|
+
for (let index = events.length - 1; index >= 0; index--) {
|
|
146
|
+
const event = events[index];
|
|
147
|
+
if (event.kind === "cancel-requested" && event.grantSequence === grantSequence)
|
|
148
|
+
return "cancel_requested";
|
|
149
|
+
if (event.kind === "authorization-expired" && event.grantSequence === grantSequence)
|
|
150
|
+
return "authorization_expired";
|
|
151
|
+
if (event.kind === "quarantined" && event.grantSequence === grantSequence)
|
|
152
|
+
return "restart_unreconciled";
|
|
153
|
+
if (event.kind === "authority-epoch-advanced" &&
|
|
154
|
+
event.transitions.some((transition) => transition.grantSequence === grantSequence))
|
|
155
|
+
return "restart_unreconciled";
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
};
|
|
159
|
+
const witnessed = new Set(events.flatMap((event) => (event.kind === "termination-observed" ? [event.grantSequence] : [])));
|
|
160
|
+
const grants = [...projection.grants.values()];
|
|
161
|
+
const blocking = grants.filter((grant) => !SETTLED_EFFECT_STATES.has(grant.state));
|
|
162
|
+
return Object.freeze({
|
|
163
|
+
epoch: projection.epoch,
|
|
164
|
+
reconciledEpoch: projection.reconciledEpoch,
|
|
165
|
+
pendingReconcile: authorityPendingReconcile(projection),
|
|
166
|
+
blockingGrants: Object.freeze(blocking.map((grant) => Object.freeze({
|
|
167
|
+
grantSequence: grant.token.grantSequence,
|
|
168
|
+
sessionId: grant.token.sessionId,
|
|
169
|
+
sessionIncarnation: grant.token.sessionIncarnation,
|
|
170
|
+
authorityEpoch: grant.token.authorityEpoch,
|
|
171
|
+
commandId: grant.commandId,
|
|
172
|
+
intentDigest: grant.intentDigest,
|
|
173
|
+
state: grant.state,
|
|
174
|
+
effectLive: grant.effectLive,
|
|
175
|
+
claims: Object.freeze(grant.claims.map((claim) => Object.freeze({
|
|
176
|
+
namespace: claim.namespace,
|
|
177
|
+
instanceId: claim.instanceId,
|
|
178
|
+
canonicalKey: claim.canonicalKey,
|
|
179
|
+
access: claim.access,
|
|
180
|
+
generation: claim.generation,
|
|
181
|
+
}))),
|
|
182
|
+
weight: grant.weight,
|
|
183
|
+
dispatchId: grant.dispatchId,
|
|
184
|
+
authorizationDeadline: grant.token.authorizationDeadline,
|
|
185
|
+
cause: grant.state === "quarantined" ? (transitionOf(grant.token.grantSequence) ?? "unwitnessed") : null,
|
|
186
|
+
terminationWitnessed: witnessed.has(grant.token.grantSequence),
|
|
187
|
+
}))),
|
|
188
|
+
settledGrantCount: grants.length - blocking.length,
|
|
189
|
+
tombstoneCount: projection.tombstones.size,
|
|
190
|
+
incarnations: Object.freeze([...projection.incarnations.entries()].map(([sessionId, incarnation]) => Object.freeze({ sessionId, incarnation }))),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=run-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-status.js","sourceRoot":"","sources":["../../../src/core/verified-run/run-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { MAX_VERIFIED_RUN_GENERATIONS } from \"omk-protocol\";\nimport { SETTLED_EFFECT_STATES } from \"../../coordination/types.ts\";\nimport type { AuthorityEvent, AuthorityGrantRecord, AuthorityProjection } from \"./authority-events.ts\";\nimport { authorityPendingReconcile } from \"./authority-events.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\n\n/**\n * Derived lifecycle/recovery status surfaces (WP06).\n *\n * Everything here is a pure function of the replayed journals: the run\n * projection and the authority projection/records are the single source of\n * truth, and this module never invents parallel status strings — `lifecycle`\n * and `completion` are named projections of the same facts the axes already\n * report (`execution`, `settlement`, `verification`, `application`,\n * `publication`, `failure`, grant states and transition events).\n *\n * Separations the surface guarantees (docs/03, docs/12 WP06):\n * - cancellation requested vs terminated: an authority grant that got\n * `cancel-requested` with a live effect stays `quarantined` and keeps its\n * claims until `termination-observed` witnesses it;\n * - prompt settled vs verified vs published: `completion` is a three-tier\n * ladder (`prompt_settled` < `verification_passed` < `published`) derived\n * from candidate/receipt/publication facts, never from prose;\n * - accepted vs published: `lifecycle: \"accepted\"` is the verified,\n * publishable state; `published` requires the CAS result record;\n * - recovery/unknown states vs clean success: `cleanSuccess` is true only\n * for a terminal run with an empty `unresolved` list — quarantine,\n * unverified termination, a refused or half-published outbox entry and a\n * violated check set all stay visible instead of collapsing into success.\n */\n\n/** Single-token lifecycle derived from the run axes; snake_case matches the projection vocabulary. */\nexport type RunLifecycle =\n\t| \"queued\"\n\t| \"running\"\n\t| \"verifying\"\n\t| \"resuming\"\n\t| \"blocked\"\n\t| \"accepted\"\n\t| \"published\"\n\t| \"violated\"\n\t| \"cancelled\"\n\t| \"failed\"\n\t| \"quarantined\";\n\n/** User-visible completion ladder: prompt-settled < verification-passed < published (docs/03 §10). */\nexport type RunCompletion = \"none\" | \"prompt_settled\" | \"verification_passed\" | \"published\";\n\n/** Machine-collected open concerns; a clean terminal run carries none. */\nexport type RunUnresolved =\n\t| \"pending_effects\"\n\t| \"verification_pending\"\n\t| \"verification_violated\"\n\t| \"publication_intent\"\n\t| \"publication_refused\"\n\t| \"publication_reconciliation_required\";\n\nexport interface RunRecoveryCommand {\n\t/** The recovery CLI verb to run. */\n\treadonly command: \"resume\" | \"retry_tasks\" | \"restart_writer\" | \"publish\";\n\t/** Exact target identity the command must name. */\n\treadonly runId: string;\n\treadonly revision: number;\n\treadonly generation: number;\n\t/** Scope: candidate/base digests or task ids the command binds. */\n\treadonly scope: {\n\t\treadonly candidateDigest?: string;\n\t\treadonly baseDigest?: string;\n\t\treadonly taskIds?: readonly string[];\n\t};\n\t/**\n\t * Projection-level eligibility only — deadline, clock and namespace\n\t * readiness are host-checked by `inspectRecovery`/`inspectWriterRecovery`/\n\t * `inspectTaskRecovery`; this hint never claims the command will succeed.\n\t */\n\treadonly advisory: true;\n}\n\nexport interface RunStatus {\n\treadonly runId: string;\n\treadonly revision: number;\n\treadonly generation: number;\n\treadonly lifecycle: RunLifecycle;\n\treadonly completion: RunCompletion;\n\t/** True only for a terminal run that reached verification_passed/published with zero unresolved concerns. */\n\treadonly cleanSuccess: boolean;\n\treadonly terminal: boolean;\n\treadonly unresolved: readonly RunUnresolved[];\n\t/** Verbatim axes, same strings the journal projection computes. */\n\treadonly execution: RunProjection[\"execution\"];\n\treadonly settlement: RunProjection[\"settlement\"];\n\treadonly verification: RunProjection[\"verification\"];\n\treadonly application: RunProjection[\"application\"];\n\treadonly publication: {\n\t\treadonly state: RunProjection[\"publication\"];\n\t\treadonly commandId: string | null;\n\t\treadonly candidateOid: string | null;\n\t\treadonly ref: string | null;\n\t\treadonly failure: string | null;\n\t};\n\t/** Failure code as recorded (`descendant_escape`, `termination_unverified`, `cancelled`, …). */\n\treadonly cause: string | null;\n\treadonly pendingEffects: number;\n\treadonly writerOpen: boolean;\n\treadonly recovery: RunProjection[\"lastRecovery\"];\n\treadonly recoveryCommands: readonly RunRecoveryCommand[];\n}\n\n/** Derive the status view; pure projection truth in, status out, no I/O. */\nexport function deriveRunStatus(state: RunProjection): RunStatus {\n\tconst unresolved: RunUnresolved[] = [];\n\tif (state.activeExecutionIds.length > 0 || state.writerOpen) unresolved.push(\"pending_effects\");\n\tif (state.candidateDigest && !state.receiptDigest && state.execution !== \"failed\" && state.execution !== \"ready\")\n\t\tunresolved.push(\"verification_pending\");\n\tif (state.verification === \"violated\") unresolved.push(\"verification_violated\");\n\tif (state.publication === \"intent\") unresolved.push(\"publication_intent\");\n\tif (state.publication === \"failed\") unresolved.push(\"publication_refused\");\n\tif (state.publication === \"reconciliation_required\") unresolved.push(\"publication_reconciliation_required\");\n\n\tconst completion: RunCompletion =\n\t\tstate.publication === \"accepted\"\n\t\t\t? \"published\"\n\t\t\t: state.verification === \"verified\"\n\t\t\t\t? \"verification_passed\"\n\t\t\t\t: state.candidateDigest\n\t\t\t\t\t? \"prompt_settled\"\n\t\t\t\t\t: \"none\";\n\n\tconst terminal = state.execution === \"succeeded\" || state.execution === \"failed\";\n\tlet lifecycle: RunLifecycle;\n\tif (state.settlement === \"quarantined\") lifecycle = \"quarantined\";\n\telse if (state.execution === \"ready\") lifecycle = \"queued\";\n\telse if (state.execution === \"running\") {\n\t\tif (state.lastRecovery && state.lastRecovery.generation === state.generation) lifecycle = \"resuming\";\n\t\telse if (state.candidateDigest && !state.receiptDigest) lifecycle = \"verifying\";\n\t\telse lifecycle = \"running\";\n\t} else if (state.execution === \"paused\") lifecycle = \"blocked\";\n\telse if (state.execution === \"failed\") lifecycle = state.failure === \"cancelled\" ? \"cancelled\" : \"failed\";\n\telse if (state.verification === \"verified\") lifecycle = state.publication === \"accepted\" ? \"published\" : \"accepted\";\n\telse lifecycle = \"violated\";\n\n\treturn Object.freeze({\n\t\trunId: state.runId,\n\t\trevision: state.revision,\n\t\tgeneration: state.generation,\n\t\tlifecycle,\n\t\tcompletion,\n\t\t// Clean success means the verification ladder actually climbed: a\n\t\t// terminal cancel/failure/violation, or a verified run with an open\n\t\t// publish outbox, never reports clean.\n\t\tcleanSuccess:\n\t\t\tterminal && unresolved.length === 0 && (completion === \"verification_passed\" || completion === \"published\"),\n\t\tterminal,\n\t\tunresolved: Object.freeze(unresolved),\n\t\texecution: state.execution,\n\t\tsettlement: state.settlement,\n\t\tverification: state.verification,\n\t\tapplication: state.application,\n\t\tpublication: Object.freeze({\n\t\t\tstate: state.publication,\n\t\t\tcommandId: state.publicationCommandId,\n\t\t\tcandidateOid: state.publicationCandidateOid,\n\t\t\tref: state.publicationRef,\n\t\t\tfailure: state.publicationFailure,\n\t\t}),\n\t\tcause: state.failure,\n\t\tpendingEffects: state.activeExecutionIds.length,\n\t\twriterOpen: state.writerOpen,\n\t\trecovery: state.lastRecovery,\n\t\trecoveryCommands: Object.freeze(recoveryCommands(state)),\n\t});\n}\n\nfunction recoveryCommands(state: RunProjection): RunRecoveryCommand[] {\n\tconst commands: RunRecoveryCommand[] = [];\n\tif (state.generation >= MAX_VERIFIED_RUN_GENERATIONS) return commands;\n\tconst base = { runId: state.runId, revision: state.revision, generation: state.generation } as const;\n\t// A frozen candidate can be re-verified under a new generation (resume gate\n\t// mirrors `assertCandidateRecoverable`: candidate, no receipt, not failed).\n\tif (\n\t\tstate.candidateDigest &&\n\t\t!state.receiptDigest &&\n\t\t!state.writerOpen &&\n\t\tstate.execution !== \"failed\" &&\n\t\tstate.execution !== \"ready\"\n\t) {\n\t\tcommands.push({\n\t\t\t...base,\n\t\t\tcommand: \"resume\",\n\t\t\tscope: { candidateDigest: state.candidateDigest },\n\t\t\tadvisory: true,\n\t\t});\n\t}\n\t// DAG tasks can be retried from the input checkpoint (retry gate mirrors\n\t// `commandDisposition`: input checkpoint present, tasks exist).\n\tif (state.inputDigest && state.tasks.length > 0) {\n\t\tconst failed = state.tasks\n\t\t\t.filter((task) => task.status === \"failed\" || (task.status === \"pending\" && task.attempt > 0))\n\t\t\t.map((task) => task.taskId);\n\t\tif (failed.length > 0) {\n\t\t\tcommands.push({\n\t\t\t\t...base,\n\t\t\t\tcommand: \"retry_tasks\",\n\t\t\t\tscope: { baseDigest: state.inputDigest, taskIds: Object.freeze(failed) },\n\t\t\t\tadvisory: true,\n\t\t\t});\n\t\t}\n\t}\n\t// A writer that never produced a candidate restarts from the input\n\t// checkpoint (non-DAG profiles only; DAG recovery is retry_tasks).\n\tif (state.inputDigest && !state.candidateDigest && state.tasks.length === 0 && state.execution !== \"ready\") {\n\t\tcommands.push({\n\t\t\t...base,\n\t\t\tcommand: \"restart_writer\",\n\t\t\tscope: { baseDigest: state.inputDigest },\n\t\t\tadvisory: true,\n\t\t});\n\t}\n\t// The publish outbox: a verified, settled run can publish; a refused or\n\t// half-published intent is re-driven by the same command identity.\n\tif (\n\t\tstate.application === \"candidate_ready\" &&\n\t\tstate.settlement === \"settled\" &&\n\t\tstate.receiptDigest &&\n\t\tstate.candidateDigest &&\n\t\t(state.publication === \"none\" || state.publication === \"failed\" || state.publication === \"intent\")\n\t) {\n\t\tcommands.push({\n\t\t\t...base,\n\t\t\tcommand: \"publish\",\n\t\t\tscope: { candidateDigest: state.candidateDigest },\n\t\t\tadvisory: true,\n\t\t});\n\t}\n\treturn commands;\n}\n\nexport type AuthorityGrantCause = \"cancel_requested\" | \"authorization_expired\" | \"restart_unreconciled\" | \"unwitnessed\";\n\nexport interface AuthorityGrantStatus {\n\treadonly grantSequence: string;\n\treadonly sessionId: string;\n\treadonly sessionIncarnation: string;\n\treadonly authorityEpoch: string;\n\treadonly commandId: string;\n\treadonly intentDigest: string;\n\t/** Verbatim grant state — the authority projection's own vocabulary. */\n\treadonly state: AuthorityGrantRecord[\"state\"];\n\treadonly effectLive: boolean;\n\t/** Claims this grant still holds — what it blocks, with exact scope. */\n\treadonly claims: readonly {\n\t\treadonly namespace: string;\n\t\treadonly instanceId: string;\n\t\treadonly canonicalKey: string;\n\t\treadonly access: string;\n\t\treadonly generation: string;\n\t}[];\n\treadonly weight: number;\n\treadonly dispatchId: string | null;\n\treadonly authorizationDeadline: number;\n\t/** Why the grant is in this state; null when records were not supplied. */\n\treadonly cause: AuthorityGrantCause | null;\n\t/**\n\t * Cancellation requested vs terminated: true only when a\n\t * `termination-observed` record witnessed this exact grant.\n\t */\n\treadonly terminationWitnessed: boolean;\n}\n\nexport interface AuthorityStatus {\n\treadonly epoch: string | null;\n\treadonly reconciledEpoch: string | null;\n\treadonly pendingReconcile: boolean;\n\t/** Grants still holding claims — what is blocking new admission. */\n\treadonly blockingGrants: readonly AuthorityGrantStatus[];\n\treadonly settledGrantCount: number;\n\treadonly tombstoneCount: number;\n\treadonly incarnations: readonly { readonly sessionId: string; readonly incarnation: string }[];\n}\n\n/**\n * Derive the authority status from the committed projection; pass the journal\n * records' events so quarantine/cancel causes stay distinguishable — the\n * projection alone intentionally does not restate them.\n */\nexport function deriveAuthorityStatus(\n\tprojection: AuthorityProjection,\n\tevents: readonly AuthorityEvent[] = [],\n): AuthorityStatus {\n\tconst transitionOf = (grantSequence: string): AuthorityGrantCause | null => {\n\t\tfor (let index = events.length - 1; index >= 0; index--) {\n\t\t\tconst event = events[index]!;\n\t\t\tif (event.kind === \"cancel-requested\" && event.grantSequence === grantSequence) return \"cancel_requested\";\n\t\t\tif (event.kind === \"authorization-expired\" && event.grantSequence === grantSequence)\n\t\t\t\treturn \"authorization_expired\";\n\t\t\tif (event.kind === \"quarantined\" && event.grantSequence === grantSequence) return \"restart_unreconciled\";\n\t\t\tif (\n\t\t\t\tevent.kind === \"authority-epoch-advanced\" &&\n\t\t\t\tevent.transitions.some((transition) => transition.grantSequence === grantSequence)\n\t\t\t)\n\t\t\t\treturn \"restart_unreconciled\";\n\t\t}\n\t\treturn null;\n\t};\n\tconst witnessed = new Set(\n\t\tevents.flatMap((event) => (event.kind === \"termination-observed\" ? [event.grantSequence] : [])),\n\t);\n\tconst grants = [...projection.grants.values()];\n\tconst blocking = grants.filter((grant) => !SETTLED_EFFECT_STATES.has(grant.state));\n\treturn Object.freeze({\n\t\tepoch: projection.epoch,\n\t\treconciledEpoch: projection.reconciledEpoch,\n\t\tpendingReconcile: authorityPendingReconcile(projection),\n\t\tblockingGrants: Object.freeze(\n\t\t\tblocking.map((grant) =>\n\t\t\t\tObject.freeze({\n\t\t\t\t\tgrantSequence: grant.token.grantSequence,\n\t\t\t\t\tsessionId: grant.token.sessionId,\n\t\t\t\t\tsessionIncarnation: grant.token.sessionIncarnation,\n\t\t\t\t\tauthorityEpoch: grant.token.authorityEpoch,\n\t\t\t\t\tcommandId: grant.commandId,\n\t\t\t\t\tintentDigest: grant.intentDigest,\n\t\t\t\t\tstate: grant.state,\n\t\t\t\t\teffectLive: grant.effectLive,\n\t\t\t\t\tclaims: Object.freeze(\n\t\t\t\t\t\tgrant.claims.map((claim) =>\n\t\t\t\t\t\t\tObject.freeze({\n\t\t\t\t\t\t\t\tnamespace: claim.namespace,\n\t\t\t\t\t\t\t\tinstanceId: claim.instanceId,\n\t\t\t\t\t\t\t\tcanonicalKey: claim.canonicalKey,\n\t\t\t\t\t\t\t\taccess: claim.access,\n\t\t\t\t\t\t\t\tgeneration: claim.generation,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\tweight: grant.weight,\n\t\t\t\t\tdispatchId: grant.dispatchId,\n\t\t\t\t\tauthorizationDeadline: grant.token.authorizationDeadline,\n\t\t\t\t\tcause: grant.state === \"quarantined\" ? (transitionOf(grant.token.grantSequence) ?? \"unwitnessed\") : null,\n\t\t\t\t\tterminationWitnessed: witnessed.has(grant.token.grantSequence),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t\tsettledGrantCount: grants.length - blocking.length,\n\t\ttombstoneCount: projection.tombstones.size,\n\t\tincarnations: Object.freeze(\n\t\t\t[...projection.incarnations.entries()].map(([sessionId, incarnation]) =>\n\t\t\t\tObject.freeze({ sessionId, incarnation }),\n\t\t\t),\n\t\t),\n\t});\n}\n"]}
|
|
@@ -64,7 +64,32 @@ export type RunEvent = DagEvent | {
|
|
|
64
64
|
} | {
|
|
65
65
|
readonly kind: "failed";
|
|
66
66
|
readonly code: string;
|
|
67
|
+
} | {
|
|
68
|
+
readonly kind: "publish_intent";
|
|
69
|
+
readonly commandId: string;
|
|
70
|
+
readonly candidateDigest: string;
|
|
71
|
+
readonly candidateOid: string;
|
|
72
|
+
readonly parentOid: string;
|
|
73
|
+
readonly targetRef: string;
|
|
74
|
+
readonly receiptDigest: string;
|
|
75
|
+
readonly policyDigest: string;
|
|
76
|
+
readonly generation: number;
|
|
77
|
+
} | {
|
|
78
|
+
readonly kind: "published";
|
|
79
|
+
readonly commandId: string;
|
|
80
|
+
readonly candidateOid: string;
|
|
81
|
+
readonly previousOid: string;
|
|
82
|
+
} | {
|
|
83
|
+
readonly kind: "publish_failed";
|
|
84
|
+
readonly commandId: string;
|
|
85
|
+
readonly code: string;
|
|
67
86
|
};
|
|
87
|
+
/** The latest recovery command that opened a new generation, durable journal truth. */
|
|
88
|
+
export interface RunRecoveryMarker {
|
|
89
|
+
readonly kind: "resumed" | "writer_restarted" | "tasks_retried";
|
|
90
|
+
readonly commandId: string;
|
|
91
|
+
readonly generation: number;
|
|
92
|
+
}
|
|
68
93
|
export interface RunProjection {
|
|
69
94
|
readonly runId: string;
|
|
70
95
|
readonly revision: number;
|
|
@@ -73,10 +98,16 @@ export interface RunProjection {
|
|
|
73
98
|
readonly settlement: "open" | "draining" | "settled" | "quarantined";
|
|
74
99
|
readonly verification: "not_requested" | "verified" | "violated" | "inconclusive";
|
|
75
100
|
readonly application: "not_requested" | "candidate_ready";
|
|
101
|
+
readonly publication: "none" | "intent" | "accepted" | "failed" | "reconciliation_required";
|
|
102
|
+
readonly publicationCandidateOid: string | null;
|
|
103
|
+
readonly publicationRef: string | null;
|
|
104
|
+
readonly publicationCommandId: string | null;
|
|
105
|
+
readonly publicationFailure: string | null;
|
|
76
106
|
readonly candidateDigest: string | null;
|
|
77
107
|
readonly inputDigest: string | null;
|
|
78
108
|
readonly receiptDigest: string | null;
|
|
79
109
|
readonly failure: string | null;
|
|
110
|
+
readonly lastRecovery: RunRecoveryMarker | null;
|
|
80
111
|
readonly activeExecutionIds: readonly string[];
|
|
81
112
|
readonly writerOpen: boolean;
|
|
82
113
|
readonly modelRequests: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-types.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/run-types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"run-types.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/run-types.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tRunContract,\n\tRunResumeCommand,\n\tRunStartCommand,\n\tRunTaskRetryCommand,\n\tRunWriterRestartCommand,\n} from \"omk-protocol\";\nimport type { DagEvent, RunTaskCheckpoint, RunTaskProjection } from \"./dag-types.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport type { RecoveryBudget } from \"./recovery-clock.ts\";\n\nexport type RunEvent =\n\t| DagEvent\n\t| { readonly kind: \"created\"; readonly contract: RunContract; readonly command: RunStartCommand }\n\t| {\n\t\t\treadonly kind: \"budget_anchored\";\n\t\t\treadonly budget: RecoveryBudget;\n\t\t\treadonly environmentDigest: string;\n\t\t\treadonly driver: \"linux-pidns-gate-v1\";\n\t }\n\t| {\n\t\t\treadonly kind: \"dispatch\";\n\t\t\treadonly executionId: string;\n\t\t\treadonly role: \"writer\" | \"verifier\";\n\t\t\treadonly claimId: string | null;\n\t\t\treadonly taskId?: string;\n\t }\n\t| { readonly kind: \"input_checkpoint\"; readonly digest: string }\n\t| { readonly kind: \"process_ready\"; readonly executionId: string; readonly identity: NamespaceIdentity }\n\t| { readonly kind: \"writer_opened\" }\n\t| { readonly kind: \"model_request\"; readonly requestId: string }\n\t| { readonly kind: \"writer_closed\"; readonly completed: boolean }\n\t| { readonly kind: \"exited\"; readonly executionId: string; readonly failure: string | null }\n\t| {\n\t\t\treadonly kind: \"candidate\";\n\t\t\treadonly digest: string;\n\t\t\treadonly observedMs?: number;\n\t\t\treadonly verificationDeadlineMs?: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"resumed\";\n\t\t\treadonly command: RunResumeCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"writer_restarted\";\n\t\t\treadonly command: RunWriterRestartCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"tasks_retried\";\n\t\t\treadonly command: RunTaskRetryCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t\t\treadonly adopted: readonly RunTaskCheckpoint[];\n\t }\n\t| { readonly kind: \"evaluated\"; readonly receiptDigest: string; readonly verified: boolean }\n\t| { readonly kind: \"failed\"; readonly code: string }\n\t| {\n\t\t\treadonly kind: \"publish_intent\";\n\t\t\treadonly commandId: string;\n\t\t\treadonly candidateDigest: string;\n\t\t\treadonly candidateOid: string;\n\t\t\treadonly parentOid: string;\n\t\t\treadonly targetRef: string;\n\t\t\treadonly receiptDigest: string;\n\t\t\treadonly policyDigest: string;\n\t\t\treadonly generation: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"published\";\n\t\t\treadonly commandId: string;\n\t\t\treadonly candidateOid: string;\n\t\t\treadonly previousOid: string;\n\t }\n\t| { readonly kind: \"publish_failed\"; readonly commandId: string; readonly code: string };\n\n/** The latest recovery command that opened a new generation, durable journal truth. */\nexport interface RunRecoveryMarker {\n\treadonly kind: \"resumed\" | \"writer_restarted\" | \"tasks_retried\";\n\treadonly commandId: string;\n\treadonly generation: number;\n}\n\nexport interface RunProjection {\n\treadonly runId: string;\n\treadonly revision: number;\n\treadonly generation: number;\n\treadonly execution: \"ready\" | \"running\" | \"paused\" | \"succeeded\" | \"failed\";\n\treadonly settlement: \"open\" | \"draining\" | \"settled\" | \"quarantined\";\n\treadonly verification: \"not_requested\" | \"verified\" | \"violated\" | \"inconclusive\";\n\treadonly application: \"not_requested\" | \"candidate_ready\";\n\treadonly publication: \"none\" | \"intent\" | \"accepted\" | \"failed\" | \"reconciliation_required\";\n\treadonly publicationCandidateOid: string | null;\n\treadonly publicationRef: string | null;\n\treadonly publicationCommandId: string | null;\n\treadonly publicationFailure: string | null;\n\treadonly candidateDigest: string | null;\n\treadonly inputDigest: string | null;\n\treadonly receiptDigest: string | null;\n\treadonly failure: string | null;\n\treadonly lastRecovery: RunRecoveryMarker | null;\n\treadonly activeExecutionIds: readonly string[];\n\treadonly writerOpen: boolean;\n\treadonly modelRequests: number;\n\treadonly tasks: readonly RunTaskProjection[];\n\treadonly budget: RecoveryBudget | null;\n\treadonly environmentDigest: string | null;\n\treadonly verificationDeadlineMs: number | null;\n\treadonly lastClockMs: number | null;\n\treadonly processes: readonly { readonly executionId: string; readonly identity: NamespaceIdentity }[];\n}\n\n/** Mutable reduction bookkeeping, confined to one replay call. */\nexport interface WriterReduction {\n\treadonly contract: RunContract;\n\tstate: RunProjection;\n\twriterFinished: boolean;\n\twriterStarted: boolean;\n\tproducerStarted: boolean;\n\twriterCommands: number;\n\trequestBaseline: number;\n\treadonly requests: Set<string>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-types.js","sourceRoot":"","sources":["../../../src/core/verified-run/run-types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n\tRunContract,\n\tRunResumeCommand,\n\tRunStartCommand,\n\tRunTaskRetryCommand,\n\tRunWriterRestartCommand,\n} from \"omk-protocol\";\nimport type { DagEvent, RunTaskCheckpoint, RunTaskProjection } from \"./dag-types.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport type { RecoveryBudget } from \"./recovery-clock.ts\";\n\nexport type RunEvent =\n\t| DagEvent\n\t| { readonly kind: \"created\"; readonly contract: RunContract; readonly command: RunStartCommand }\n\t| {\n\t\t\treadonly kind: \"budget_anchored\";\n\t\t\treadonly budget: RecoveryBudget;\n\t\t\treadonly environmentDigest: string;\n\t\t\treadonly driver: \"linux-pidns-gate-v1\";\n\t }\n\t| {\n\t\t\treadonly kind: \"dispatch\";\n\t\t\treadonly executionId: string;\n\t\t\treadonly role: \"writer\" | \"verifier\";\n\t\t\treadonly claimId: string | null;\n\t\t\treadonly taskId?: string;\n\t }\n\t| { readonly kind: \"input_checkpoint\"; readonly digest: string }\n\t| { readonly kind: \"process_ready\"; readonly executionId: string; readonly identity: NamespaceIdentity }\n\t| { readonly kind: \"writer_opened\" }\n\t| { readonly kind: \"model_request\"; readonly requestId: string }\n\t| { readonly kind: \"writer_closed\"; readonly completed: boolean }\n\t| { readonly kind: \"exited\"; readonly executionId: string; readonly failure: string | null }\n\t| {\n\t\t\treadonly kind: \"candidate\";\n\t\t\treadonly digest: string;\n\t\t\treadonly observedMs?: number;\n\t\t\treadonly verificationDeadlineMs?: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"resumed\";\n\t\t\treadonly command: RunResumeCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"writer_restarted\";\n\t\t\treadonly command: RunWriterRestartCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"tasks_retried\";\n\t\t\treadonly command: RunTaskRetryCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t\t\treadonly adopted: readonly RunTaskCheckpoint[];\n\t }\n\t| { readonly kind: \"evaluated\"; readonly receiptDigest: string; readonly verified: boolean }\n\t| { readonly kind: \"failed\"; readonly code: string };\n\nexport interface RunProjection {\n\treadonly runId: string;\n\treadonly revision: number;\n\treadonly generation: number;\n\treadonly execution: \"ready\" | \"running\" | \"paused\" | \"succeeded\" | \"failed\";\n\treadonly settlement: \"open\" | \"draining\" | \"settled\" | \"quarantined\";\n\treadonly verification: \"not_requested\" | \"verified\" | \"violated\" | \"inconclusive\";\n\treadonly application: \"not_requested\" | \"candidate_ready\";\n\treadonly candidateDigest: string | null;\n\treadonly inputDigest: string | null;\n\treadonly receiptDigest: string | null;\n\treadonly failure: string | null;\n\treadonly activeExecutionIds: readonly string[];\n\treadonly writerOpen: boolean;\n\treadonly modelRequests: number;\n\treadonly tasks: readonly RunTaskProjection[];\n\treadonly budget: RecoveryBudget | null;\n\treadonly environmentDigest: string | null;\n\treadonly verificationDeadlineMs: number | null;\n\treadonly lastClockMs: number | null;\n\treadonly processes: readonly { readonly executionId: string; readonly identity: NamespaceIdentity }[];\n}\n\n/** Mutable reduction bookkeeping, confined to one replay call. */\nexport interface WriterReduction {\n\treadonly contract: RunContract;\n\tstate: RunProjection;\n\twriterFinished: boolean;\n\twriterStarted: boolean;\n\tproducerStarted: boolean;\n\twriterCommands: number;\n\trequestBaseline: number;\n\treadonly requests: Set<string>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run-types.js","sourceRoot":"","sources":["../../../src/core/verified-run/run-types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n\tRunContract,\n\tRunResumeCommand,\n\tRunStartCommand,\n\tRunTaskRetryCommand,\n\tRunWriterRestartCommand,\n} from \"omk-protocol\";\nimport type { DagEvent, RunTaskCheckpoint, RunTaskProjection } from \"./dag-types.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport type { RecoveryBudget } from \"./recovery-clock.ts\";\n\nexport type RunEvent =\n\t| DagEvent\n\t| { readonly kind: \"created\"; readonly contract: RunContract; readonly command: RunStartCommand }\n\t| {\n\t\t\treadonly kind: \"budget_anchored\";\n\t\t\treadonly budget: RecoveryBudget;\n\t\t\treadonly environmentDigest: string;\n\t\t\treadonly driver: \"linux-pidns-gate-v1\";\n\t }\n\t| {\n\t\t\treadonly kind: \"dispatch\";\n\t\t\treadonly executionId: string;\n\t\t\treadonly role: \"writer\" | \"verifier\";\n\t\t\treadonly claimId: string | null;\n\t\t\treadonly taskId?: string;\n\t }\n\t| { readonly kind: \"input_checkpoint\"; readonly digest: string }\n\t| { readonly kind: \"process_ready\"; readonly executionId: string; readonly identity: NamespaceIdentity }\n\t| { readonly kind: \"writer_opened\" }\n\t| { readonly kind: \"model_request\"; readonly requestId: string }\n\t| { readonly kind: \"writer_closed\"; readonly completed: boolean }\n\t| { readonly kind: \"exited\"; readonly executionId: string; readonly failure: string | null }\n\t| {\n\t\t\treadonly kind: \"candidate\";\n\t\t\treadonly digest: string;\n\t\t\treadonly observedMs?: number;\n\t\t\treadonly verificationDeadlineMs?: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"resumed\";\n\t\t\treadonly command: RunResumeCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"writer_restarted\";\n\t\t\treadonly command: RunWriterRestartCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly kind: \"tasks_retried\";\n\t\t\treadonly command: RunTaskRetryCommand;\n\t\t\treadonly observedMs: number;\n\t\t\treadonly reconciledExecutionIds: readonly string[];\n\t\t\treadonly adopted: readonly RunTaskCheckpoint[];\n\t }\n\t| { readonly kind: \"evaluated\"; readonly receiptDigest: string; readonly verified: boolean }\n\t| { readonly kind: \"failed\"; readonly code: string }\n\t| {\n\t\t\treadonly kind: \"publish_intent\";\n\t\t\treadonly commandId: string;\n\t\t\treadonly candidateDigest: string;\n\t\t\treadonly candidateOid: string;\n\t\t\treadonly parentOid: string;\n\t\t\treadonly targetRef: string;\n\t\t\treadonly receiptDigest: string;\n\t\t\treadonly policyDigest: string;\n\t\t\treadonly generation: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"published\";\n\t\t\treadonly commandId: string;\n\t\t\treadonly candidateOid: string;\n\t\t\treadonly previousOid: string;\n\t }\n\t| { readonly kind: \"publish_failed\"; readonly commandId: string; readonly code: string };\n\n/** The latest recovery command that opened a new generation, durable journal truth. */\nexport interface RunRecoveryMarker {\n\treadonly kind: \"resumed\" | \"writer_restarted\" | \"tasks_retried\";\n\treadonly commandId: string;\n\treadonly generation: number;\n}\n\nexport interface RunProjection {\n\treadonly runId: string;\n\treadonly revision: number;\n\treadonly generation: number;\n\treadonly execution: \"ready\" | \"running\" | \"paused\" | \"succeeded\" | \"failed\";\n\treadonly settlement: \"open\" | \"draining\" | \"settled\" | \"quarantined\";\n\treadonly verification: \"not_requested\" | \"verified\" | \"violated\" | \"inconclusive\";\n\treadonly application: \"not_requested\" | \"candidate_ready\";\n\treadonly publication: \"none\" | \"intent\" | \"accepted\" | \"failed\" | \"reconciliation_required\";\n\treadonly publicationCandidateOid: string | null;\n\treadonly publicationRef: string | null;\n\treadonly publicationCommandId: string | null;\n\treadonly publicationFailure: string | null;\n\treadonly candidateDigest: string | null;\n\treadonly inputDigest: string | null;\n\treadonly receiptDigest: string | null;\n\treadonly failure: string | null;\n\treadonly lastRecovery: RunRecoveryMarker | null;\n\treadonly activeExecutionIds: readonly string[];\n\treadonly writerOpen: boolean;\n\treadonly modelRequests: number;\n\treadonly tasks: readonly RunTaskProjection[];\n\treadonly budget: RecoveryBudget | null;\n\treadonly environmentDigest: string | null;\n\treadonly verificationDeadlineMs: number | null;\n\treadonly lastClockMs: number | null;\n\treadonly processes: readonly { readonly executionId: string; readonly identity: NamespaceIdentity }[];\n}\n\n/** Mutable reduction bookkeeping, confined to one replay call. */\nexport interface WriterReduction {\n\treadonly contract: RunContract;\n\tstate: RunProjection;\n\twriterFinished: boolean;\n\twriterStarted: boolean;\n\tproducerStarted: boolean;\n\twriterCommands: number;\n\trequestBaseline: number;\n\treadonly requests: Set<string>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/storage.ts"],"names":[],"mappings":"AAMA,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,IAAI,EAAE,MAAM,EAIvB;CACD;AAED,eAAO,MAAM,WAAW,yDAA2F,CAAC;AACpH,eAAO,MAAM,YAAY,4BAAgE,CAAC;AAE1F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAetE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,OAAO,CAOlE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAOlE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlE;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAwBtF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAElD","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, join, relative, resolve } from \"node:path\";\nimport {
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/storage.ts"],"names":[],"mappings":"AAMA,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,IAAI,EAAE,MAAM,EAIvB;CACD;AAED,eAAO,MAAM,WAAW,yDAA2F,CAAC;AACpH,eAAO,MAAM,YAAY,4BAAgE,CAAC;AAE1F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAetE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,OAAO,CAOlE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAOlE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlE;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAwBtF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAElD","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, join, relative, resolve } from \"node:path\";\nimport { canonicalJson } from \"../canonical-json.ts\";\nimport { writeExclusiveFileDurablySync } from \"../durable-file-io.ts\";\n\nexport class VerifiedRunError extends Error {\n\treadonly code: string;\n\tconstructor(code: string) {\n\t\tsuper(`verified-run: ${code}`);\n\t\tthis.name = \"VerifiedRunError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport const digestBytes = (bytes: Uint8Array | string): string => createHash(\"sha256\").update(bytes).digest(\"hex\");\nexport const digestObject = (value: unknown): string => digestBytes(canonicalJson(value));\n\nexport function readRegularFile(path: string, maxBytes: number): Buffer {\n\tconst fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);\n\ttry {\n\t\tconst before = fstatSync(fd, { bigint: true });\n\t\tif (!before.isFile() || before.nlink !== 1n) throw new VerifiedRunError(\"file_type\");\n\t\tif (before.size > BigInt(maxBytes)) throw new VerifiedRunError(\"storage_limit\");\n\t\tconst bytes = readFileSync(fd);\n\t\tconst after = fstatSync(fd, { bigint: true });\n\t\tif (before.size !== after.size || before.ctimeNs !== after.ctimeNs || BigInt(bytes.length) !== before.size) {\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t}\n\t\treturn bytes;\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n}\n\nexport function readJson(path: string, maxBytes = 1048576): unknown {\n\ttry {\n\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(readRegularFile(path, maxBytes)));\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError || error instanceof TypeError) throw new VerifiedRunError(\"integrity\");\n\t\tthrow error;\n\t}\n}\n\nexport function publishBytes(path: string, bytes: Uint8Array): void {\n\ttry {\n\t\twriteExclusiveFileDurablySync(path, bytes);\n\t} catch (error) {\n\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n\t\tif (!readRegularFile(path, bytes.length).equals(Buffer.from(bytes))) throw new VerifiedRunError(\"integrity\");\n\t}\n}\n\nexport function publishObject(path: string, value: unknown): string {\n\tconst bytes = Buffer.from(canonicalJson(value));\n\tpublishBytes(path, bytes);\n\treturn digestBytes(bytes);\n}\n\n/** Resolve existing parents without creating state. State must never be part of a mounted workspace. */\nexport function stateRunPath(root: string, id: string): string {\n\tif (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(id)) throw new VerifiedRunError(\"run_id\");\n\treturn join(resolve(root), id);\n}\n\nexport function assertStateOutsideWorkspace(stateRoot: string, workspace: string): void {\n\tlet cursor = resolve(stateRoot);\n\tconst tail: string[] = [];\n\twhile (true) {\n\t\ttry {\n\t\t\tcursor = join(realpathSync(cursor), ...tail);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n\t\t\ttail.unshift(basename(cursor));\n\t\t\tcursor = dirname(cursor);\n\t\t}\n\t}\n\tconst base = realpathSync(workspace);\n\tconst under = relative(base, cursor);\n\tconst contains = relative(cursor, base);\n\tif (\n\t\tunder === \"\" ||\n\t\t(!under.startsWith(\"../\") && under !== \"..\") ||\n\t\tcontains === \"\" ||\n\t\t(!contains.startsWith(\"../\") && contains !== \"..\")\n\t) {\n\t\tthrow new VerifiedRunError(\"state_scope\");\n\t}\n}\n\nexport function assertDirectory(path: string): void {\n\tif (!lstatSync(path).isDirectory() || realpathSync(path) !== resolve(path)) throw new VerifiedRunError(\"file_type\");\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, realpathSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { canonicalJson } from "../canonical-json.js";
|
|
4
5
|
import { writeExclusiveFileDurablySync } from "../durable-file-io.js";
|
|
5
|
-
import { canonicalJson } from "../run-journal.js";
|
|
6
6
|
export class VerifiedRunError extends Error {
|
|
7
7
|
code;
|
|
8
8
|
constructor(code) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/verified-run/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/verified-run/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, join, relative, resolve } from \"node:path\";\nimport { canonicalJson } from \"../canonical-json.ts\";\nimport { writeExclusiveFileDurablySync } from \"../durable-file-io.ts\";\n\nexport class VerifiedRunError extends Error {\n\treadonly code: string;\n\tconstructor(code: string) {\n\t\tsuper(`verified-run: ${code}`);\n\t\tthis.name = \"VerifiedRunError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport const digestBytes = (bytes: Uint8Array | string): string => createHash(\"sha256\").update(bytes).digest(\"hex\");\nexport const digestObject = (value: unknown): string => digestBytes(canonicalJson(value));\n\nexport function readRegularFile(path: string, maxBytes: number): Buffer {\n\tconst fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);\n\ttry {\n\t\tconst before = fstatSync(fd, { bigint: true });\n\t\tif (!before.isFile() || before.nlink !== 1n) throw new VerifiedRunError(\"file_type\");\n\t\tif (before.size > BigInt(maxBytes)) throw new VerifiedRunError(\"storage_limit\");\n\t\tconst bytes = readFileSync(fd);\n\t\tconst after = fstatSync(fd, { bigint: true });\n\t\tif (before.size !== after.size || before.ctimeNs !== after.ctimeNs || BigInt(bytes.length) !== before.size) {\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t}\n\t\treturn bytes;\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n}\n\nexport function readJson(path: string, maxBytes = 1048576): unknown {\n\ttry {\n\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(readRegularFile(path, maxBytes)));\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError || error instanceof TypeError) throw new VerifiedRunError(\"integrity\");\n\t\tthrow error;\n\t}\n}\n\nexport function publishBytes(path: string, bytes: Uint8Array): void {\n\ttry {\n\t\twriteExclusiveFileDurablySync(path, bytes);\n\t} catch (error) {\n\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n\t\tif (!readRegularFile(path, bytes.length).equals(Buffer.from(bytes))) throw new VerifiedRunError(\"integrity\");\n\t}\n}\n\nexport function publishObject(path: string, value: unknown): string {\n\tconst bytes = Buffer.from(canonicalJson(value));\n\tpublishBytes(path, bytes);\n\treturn digestBytes(bytes);\n}\n\n/** Resolve existing parents without creating state. State must never be part of a mounted workspace. */\nexport function stateRunPath(root: string, id: string): string {\n\tif (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(id)) throw new VerifiedRunError(\"run_id\");\n\treturn join(resolve(root), id);\n}\n\nexport function assertStateOutsideWorkspace(stateRoot: string, workspace: string): void {\n\tlet cursor = resolve(stateRoot);\n\tconst tail: string[] = [];\n\twhile (true) {\n\t\ttry {\n\t\t\tcursor = join(realpathSync(cursor), ...tail);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n\t\t\ttail.unshift(basename(cursor));\n\t\t\tcursor = dirname(cursor);\n\t\t}\n\t}\n\tconst base = realpathSync(workspace);\n\tconst under = relative(base, cursor);\n\tconst contains = relative(cursor, base);\n\tif (\n\t\tunder === \"\" ||\n\t\t(!under.startsWith(\"../\") && under !== \"..\") ||\n\t\tcontains === \"\" ||\n\t\t(!contains.startsWith(\"../\") && contains !== \"..\")\n\t) {\n\t\tthrow new VerifiedRunError(\"state_scope\");\n\t}\n}\n\nexport function assertDirectory(path: string): void {\n\tif (!lstatSync(path).isDirectory() || realpathSync(path) !== resolve(path)) throw new VerifiedRunError(\"file_type\");\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type NamespaceIdentity } from "./namespace-identity.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Owned-process supervisor boundary (WP02).
|
|
4
|
+
*
|
|
5
|
+
* Three concerns are separated here so the broker only orchestrates them:
|
|
6
|
+
*
|
|
7
|
+
* - spawn: `SUPERVISOR_SYSTEM_ARGS` + `loadSupervisorBackend` describe the only
|
|
8
|
+
* backend this package trusts — bubblewrap with `--unshare-all`, which puts
|
|
9
|
+
* the supervised command in a fresh PID namespace whose init is the only
|
|
10
|
+
* process the host can see. A platform without that backend has no way to
|
|
11
|
+
* prove termination, so callers must refuse with `unsupported_boundary`
|
|
12
|
+
* instead of degrading to best-effort signaling.
|
|
13
|
+
* - cancel: `escalateTermination` sends SIGKILL to the supervised direct
|
|
14
|
+
* child (the bwrap supervisor). `--die-with-parent` propagates death to the
|
|
15
|
+
* namespace init, and the kernel then SIGKILLs every remaining task in that
|
|
16
|
+
* namespace — including non-cooperative workers and detached (`setsid`)
|
|
17
|
+
* descendants. Signal delivery is never treated as termination.
|
|
18
|
+
* - termination witness: `probeNamespace` detects the recorded namespace
|
|
19
|
+
* init's death and `awaitBoundaryDrained` waits for it. When a PID
|
|
20
|
+
* namespace's init exits, the kernel SIGKILLs every remaining task in that
|
|
21
|
+
* namespace, so init death is the exact termination witness — a `close`
|
|
22
|
+
* event, a resolved promise, or a dead direct child with surviving
|
|
23
|
+
* descendants is not. `namespaceMemberPids` remains as a diagnostic
|
|
24
|
+
* enumeration only: host process-table scans are environment-dependent
|
|
25
|
+
* (zombies keep their ns link until reaped; foreign same-uid tasks can be
|
|
26
|
+
* unreadable) and have poisoned drains on kernels where either occurs.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SUPERVISOR_BINARY = "/usr/bin/bwrap";
|
|
29
|
+
export declare const SUPERVISOR_SYSTEM_ARGS: readonly ["--unshare-all", "--die-with-parent", "--new-session", "--cap-drop", "ALL", "--clearenv", "--ro-bind", "/usr", "/usr", "--symlink", "usr/bin", "/bin", "--symlink", "usr/lib", "/lib", "--symlink", "usr/lib64", "/lib64", "--proc", "/proc", "--dev", "/dev", "--tmpfs", "/tmp", "--setenv", "PATH", "/usr/bin:/bin", "--setenv", "LANG", "C.UTF-8"];
|
|
30
|
+
export type SupervisorChild = {
|
|
31
|
+
readonly kill: (signal: NodeJS.Signals) => boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The only termination guarantee this package honors: a private PID namespace
|
|
35
|
+
* plus the Linux bwrap supervisor. Anything else is refused at the boundary.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadSupervisorBackend(): {
|
|
38
|
+
readonly binary: string;
|
|
39
|
+
readonly args: readonly string[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* SIGKILL escalation to the supervised direct child. `--die-with-parent` makes
|
|
43
|
+
* the kernel kill the whole PID namespace once this supervisor dies, so no
|
|
44
|
+
* per-descendant signaling (which PID reuse would make unsafe) is needed.
|
|
45
|
+
*/
|
|
46
|
+
export declare function escalateTermination(child: SupervisorChild): void;
|
|
47
|
+
/**
|
|
48
|
+
* Enumerate host PIDs of every task still inside `identity.namespace`.
|
|
49
|
+
*
|
|
50
|
+
* Membership is keyed on the recorded namespace symlink, not on the init's
|
|
51
|
+
* PID: a fabricated or reaped direct child cannot mask surviving descendants.
|
|
52
|
+
*
|
|
53
|
+
* A task whose namespace link cannot be read is only a candidate member when
|
|
54
|
+
* it could belong to the recorded boundary at all. The backend's members
|
|
55
|
+
* always run under our real uid — the pid namespace is owned by a user
|
|
56
|
+
* namespace we created and `CAP_SETUID` is dropped — so a task owned by
|
|
57
|
+
* another uid, or one that vanished mid-scan, cannot be a member and is
|
|
58
|
+
* skipped. An unreadable task owned by our uid is conservatively counted:
|
|
59
|
+
* failing to prove emptiness must fail closed.
|
|
60
|
+
*/
|
|
61
|
+
export declare function namespaceMemberPids(identity: Pick<NamespaceIdentity, "namespace">): number[];
|
|
62
|
+
/** Init death terminates the whole namespace; a zombie init already proves teardown finished. */
|
|
63
|
+
export declare function probeOwnedNamespace(identity: NamespaceIdentity): "terminated" | "alive" | "unknown";
|
|
64
|
+
/**
|
|
65
|
+
* Wait for the namespace init's death within budgetMs. Init death is the
|
|
66
|
+
* termination witness: the kernel SIGKILLs every remaining task in the PID
|
|
67
|
+
* namespace when its init exits, so a drained namespace needs no process-table
|
|
68
|
+
* enumeration. `populated`/`unknown` never release claims.
|
|
69
|
+
*
|
|
70
|
+
* `unknown` is not terminal here: teardown has a transient window where the
|
|
71
|
+
* init's stat is readable but its ns link read is denied or the identity
|
|
72
|
+
* probe is inconclusive, and that window resolves to `gone` once the kernel
|
|
73
|
+
* finishes teardown. Only a probe that is still inconclusive at the deadline
|
|
74
|
+
* stays `unknown`; a still-alive init is `populated`.
|
|
75
|
+
*
|
|
76
|
+
* `drained` means the kernel has provably killed every member; a task frozen
|
|
77
|
+
* in uninterruptible kernel sleep can linger in /proc briefly afterwards —
|
|
78
|
+
* that is kernel bookkeeping, not a live boundary.
|
|
79
|
+
*/
|
|
80
|
+
export declare function awaitBoundaryDrained(identity: NamespaceIdentity, budgetMs: number): Promise<"drained" | "populated" | "unknown">;
|
|
81
|
+
//# sourceMappingURL=supervisor-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-adapter.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/supervisor-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,yBAAyB,CAAC;AAGjF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAElD,eAAO,MAAM,sBAAsB,iWA+BzB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,OAAO,CAAA;CAAE,CAAC;AAErF;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAIrG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE,CAiC5F;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,CAGnG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACzC,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC,CAQ9C","sourcesContent":["import { existsSync, readdirSync, readFileSync, readlinkSync, statSync } from \"node:fs\";\nimport { performance } from \"node:perf_hooks\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { type NamespaceIdentity, probeNamespace } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\n/**\n * Owned-process supervisor boundary (WP02).\n *\n * Three concerns are separated here so the broker only orchestrates them:\n *\n * - spawn: `SUPERVISOR_SYSTEM_ARGS` + `loadSupervisorBackend` describe the only\n * backend this package trusts — bubblewrap with `--unshare-all`, which puts\n * the supervised command in a fresh PID namespace whose init is the only\n * process the host can see. A platform without that backend has no way to\n * prove termination, so callers must refuse with `unsupported_boundary`\n * instead of degrading to best-effort signaling.\n * - cancel: `escalateTermination` sends SIGKILL to the supervised direct\n * child (the bwrap supervisor). `--die-with-parent` propagates death to the\n * namespace init, and the kernel then SIGKILLs every remaining task in that\n * namespace — including non-cooperative workers and detached (`setsid`)\n * descendants. Signal delivery is never treated as termination.\n * - termination witness: `probeNamespace` detects the recorded namespace\n * init's death and `awaitBoundaryDrained` waits for it. When a PID\n * namespace's init exits, the kernel SIGKILLs every remaining task in that\n * namespace, so init death is the exact termination witness — a `close`\n * event, a resolved promise, or a dead direct child with surviving\n * descendants is not. `namespaceMemberPids` remains as a diagnostic\n * enumeration only: host process-table scans are environment-dependent\n * (zombies keep their ns link until reaped; foreign same-uid tasks can be\n * unreadable) and have poisoned drains on kernels where either occurs.\n */\nexport const SUPERVISOR_BINARY = \"/usr/bin/bwrap\";\n\nexport const SUPERVISOR_SYSTEM_ARGS = [\n\t\"--unshare-all\",\n\t\"--die-with-parent\",\n\t\"--new-session\",\n\t\"--cap-drop\",\n\t\"ALL\",\n\t\"--clearenv\",\n\t\"--ro-bind\",\n\t\"/usr\",\n\t\"/usr\",\n\t\"--symlink\",\n\t\"usr/bin\",\n\t\"/bin\",\n\t\"--symlink\",\n\t\"usr/lib\",\n\t\"/lib\",\n\t\"--symlink\",\n\t\"usr/lib64\",\n\t\"/lib64\",\n\t\"--proc\",\n\t\"/proc\",\n\t\"--dev\",\n\t\"/dev\",\n\t\"--tmpfs\",\n\t\"/tmp\",\n\t\"--setenv\",\n\t\"PATH\",\n\t\"/usr/bin:/bin\",\n\t\"--setenv\",\n\t\"LANG\",\n\t\"C.UTF-8\",\n] as const;\n\nexport type SupervisorChild = { readonly kill: (signal: NodeJS.Signals) => boolean };\n\n/**\n * The only termination guarantee this package honors: a private PID namespace\n * plus the Linux bwrap supervisor. Anything else is refused at the boundary.\n */\nexport function loadSupervisorBackend(): { readonly binary: string; readonly args: readonly string[] } {\n\tif (process.platform !== \"linux\" || !existsSync(SUPERVISOR_BINARY))\n\t\tthrow new VerifiedRunError(\"unsupported_boundary\");\n\treturn { binary: SUPERVISOR_BINARY, args: SUPERVISOR_SYSTEM_ARGS };\n}\n\n/**\n * SIGKILL escalation to the supervised direct child. `--die-with-parent` makes\n * the kernel kill the whole PID namespace once this supervisor dies, so no\n * per-descendant signaling (which PID reuse would make unsafe) is needed.\n */\nexport function escalateTermination(child: SupervisorChild): void {\n\tchild.kill(\"SIGKILL\");\n}\n\n/**\n * Enumerate host PIDs of every task still inside `identity.namespace`.\n *\n * Membership is keyed on the recorded namespace symlink, not on the init's\n * PID: a fabricated or reaped direct child cannot mask surviving descendants.\n *\n * A task whose namespace link cannot be read is only a candidate member when\n * it could belong to the recorded boundary at all. The backend's members\n * always run under our real uid — the pid namespace is owned by a user\n * namespace we created and `CAP_SETUID` is dropped — so a task owned by\n * another uid, or one that vanished mid-scan, cannot be a member and is\n * skipped. An unreadable task owned by our uid is conservatively counted:\n * failing to prove emptiness must fail closed.\n */\nexport function namespaceMemberPids(identity: Pick<NamespaceIdentity, \"namespace\">): number[] {\n\tconst members: number[] = [];\n\t// A platform without getuid cannot exclude foreign-owned tasks, so every\n\t// unreadable entry stays a candidate member (fail closed).\n\tconst uid = typeof process.getuid === \"function\" ? process.getuid() : undefined;\n\tfor (const entry of readdirSync(\"/proc\")) {\n\t\tif (!/^\\d+$/.test(entry)) continue;\n\t\ttry {\n\t\t\tif (readlinkSync(`/proc/${entry}/ns/pid`) !== identity.namespace) continue;\n\t\t\t// A zombie still carries the namespace link until reaped, but it\n\t\t\t// cannot run: counting it as a member confuses teardown with\n\t\t\t// survival.\n\t\t\tconst stat = readFileSync(`/proc/${entry}/stat`, \"utf8\");\n\t\t\tconst state = stat\n\t\t\t\t.slice(stat.lastIndexOf(\")\") + 2)\n\t\t\t\t.trim()\n\t\t\t\t.split(/\\s+/)[0];\n\t\t\tif (state !== \"Z\" && state !== \"X\") members.push(Number(entry));\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && \"code\" in error)) continue;\n\t\t\tif (error.code === \"ENOENT\" || error.code === \"ESRCH\") continue;\n\t\t\ttry {\n\t\t\t\tif (uid === undefined || statSync(`/proc/${entry}`).uid === uid) members.push(Number(entry));\n\t\t\t} catch (statError) {\n\t\t\t\tif (\n\t\t\t\t\t!(statError instanceof Error && \"code\" in statError) ||\n\t\t\t\t\t(statError.code !== \"ENOENT\" && statError.code !== \"ESRCH\")\n\t\t\t\t)\n\t\t\t\t\tmembers.push(Number(entry));\n\t\t\t}\n\t\t}\n\t}\n\treturn members;\n}\n\n/** Init death terminates the whole namespace; a zombie init already proves teardown finished. */\nexport function probeOwnedNamespace(identity: NamespaceIdentity): \"terminated\" | \"alive\" | \"unknown\" {\n\tconst status = probeNamespace(identity);\n\treturn status === \"gone\" ? \"terminated\" : status;\n}\n\n/**\n * Wait for the namespace init's death within budgetMs. Init death is the\n * termination witness: the kernel SIGKILLs every remaining task in the PID\n * namespace when its init exits, so a drained namespace needs no process-table\n * enumeration. `populated`/`unknown` never release claims.\n *\n * `unknown` is not terminal here: teardown has a transient window where the\n * init's stat is readable but its ns link read is denied or the identity\n * probe is inconclusive, and that window resolves to `gone` once the kernel\n * finishes teardown. Only a probe that is still inconclusive at the deadline\n * stays `unknown`; a still-alive init is `populated`.\n *\n * `drained` means the kernel has provably killed every member; a task frozen\n * in uninterruptible kernel sleep can linger in /proc briefly afterwards —\n * that is kernel bookkeeping, not a live boundary.\n */\nexport async function awaitBoundaryDrained(\n\tidentity: NamespaceIdentity,\n\tbudgetMs: number,\n): Promise<\"drained\" | \"populated\" | \"unknown\"> {\n\tconst deadline = performance.now() + Math.max(0, budgetMs);\n\tfor (;;) {\n\t\tconst status = probeNamespace(identity);\n\t\tif (status === \"gone\") return \"drained\";\n\t\tif (performance.now() >= deadline) return status === \"alive\" ? \"populated\" : \"unknown\";\n\t\tawait delay(Math.min(10, Math.max(1, deadline - performance.now())));\n\t}\n}\n"]}
|