open-multi-agent-kit 0.98.4 → 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 +12 -0
- package/README.md +3 -2
- package/dist/commands/run-command.d.ts +2 -1
- package/dist/commands/run-command.d.ts.map +1 -1
- package/dist/commands/run-command.js +9 -1
- package/dist/commands/run-command.js.map +1 -1
- 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/agent-session-services.d.ts +8 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +41 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +7 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +61 -41
- package/dist/core/agent-session.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/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/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 +5 -0
- 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.map +1 -1
- package/dist/core/session-run-termination.js +14 -3
- package/dist/core/session-run-termination.js.map +1 -1
- 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 +24 -28
- package/dist/core/session-termination.js.map +1 -1
- 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/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/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 +2 -8
- 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-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +45 -31
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- 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/docs/development.md +10 -0
- package/docs/keybindings.md +1 -1
- package/docs/release-audit-0.98.5.md +84 -0
- package/docs/run-protocol.md +33 -1
- package/docs/runtime-algorithms.md +26 -0
- package/docs/sdk.md +193 -0
- package/docs/usage.md +54 -0
- package/docs/verified-run-testing.md +417 -0
- package/docs/verified-run.md +388 -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":"check-receipt.js","sourceRoot":"","sources":["../../../src/core/verified-run/check-receipt.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { RunCheck, RunContract } from \"omk-protocol\";\nimport { assertCredentialFreeEvidenceCommand } from \"../../guardrails/command-redaction.ts\";\nimport { createEvidenceReceipt, parseSha256Hex, validateEvidenceReceipt } from \"../../guardrails/evidence-receipt.ts\";\nimport { computeWorkspaceManifestSha256 } from \"../../guardrails/workspace-fingerprint.ts\";\nimport type {\n\tEvidenceCommandDescriptor,\n\tEvidenceReceipt,\n\tEvidenceReceiptDisposition,\n\tWorkspaceFingerprint,\n} from \"../../types/evidence.ts\";\nimport { redactSensitiveTextForced } from \"../redaction.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport type { SandboxOutcome } from \"./broker.ts\";\nimport type { CandidateManifest } from \"./candidate.ts\";\nimport type { CheckObservation } from \"./evidence-binding.ts\";\nimport { publishObject, readJson, VerifiedRunError } from \"./storage.ts\";\n\nfunction command(check: RunCheck): EvidenceCommandDescriptor {\n\tconst executable = check.argv[0];\n\tif (!executable) throw new VerifiedRunError(\"integrity\");\n\treturn { kind: \"argv\", executable, argv: check.argv.slice(1) };\n}\n\nexport function preflightCheckReceipts(contract: RunContract): void {\n\tfor (const check of contract.checks) assertCredentialFreeEvidenceCommand(command(check));\n}\n\nfunction fingerprint(manifest: CandidateManifest): WorkspaceFingerprint {\n\tconst files = [...manifest.files].sort((left, right) =>\n\t\tleft.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n\t);\n\tconst scope = { root: \"/workspace\", artifactPaths: files.map((file) => file.path) };\n\tconst artifacts = files.map((file) => ({\n\t\tpath: file.path,\n\t\tstate: \"file\" as const,\n\t\tsha256: parseSha256Hex(file.digest),\n\t\tsize: file.size,\n\t}));\n\treturn { kind: \"artifact-set\", scope, artifacts, manifestSha256: computeWorkspaceManifestSha256(scope, artifacts) };\n}\n\nfunction disposition(result: Pick<SandboxOutcome, \"failure\" | \"exitCode\">): EvidenceReceiptDisposition {\n\tif (result.failure === \"deadline\") return { status: \"timeout\", exitCode: null };\n\tif (result.failure === \"cancelled\" || result.failure === \"output_limit\" || result.exitCode === null)\n\t\treturn { status: \"aborted\", exitCode: null };\n\treturn result.exitCode === 0 ? { status: \"passed\", exitCode: 0 } : { status: \"failed\", exitCode: result.exitCode };\n}\n\nexport function storeCheckReceipt(\n\trunPath: string,\n\tcontract: RunContract,\n\texecution: {\n\t\treadonly check: RunCheck;\n\t\treadonly executionId: string;\n\t\treadonly result: SandboxOutcome;\n\t\treadonly timeoutMs: number;\n\t\treadonly manifest: CandidateManifest;\n\t},\n): string {\n\tconst workspace = fingerprint(execution.manifest);\n\tconst result = execution.result;\n\tconst receipt = createEvidenceReceipt({\n\t\treceiptId: execution.executionId,\n\t\tgoalId: contract.runId,\n\t\tclaim: `Exact stdout for ${execution.check.claimId}`,\n\t\tcommand: command(execution.check),\n\t\tcwd: \"/workspace\",\n\t\ttimeoutMs: execution.timeoutMs,\n\t\tstartedAt: result.startedAt,\n\t\tfinishedAt: result.finishedAt,\n\t\tdurationMs: Date.parse(result.finishedAt) - Date.parse(result.startedAt),\n\t\tworkspaceBefore: workspace,\n\t\tworkspaceAfter: workspace,\n\t\texecutor: \"internal\",\n\t\ttoolCallId: execution.executionId,\n\t\talreadyRedactedOutput: {\n\t\t\tredactionPolicyId: \"omk-verified-run-v1+forced-text+prefix-32k-per-stream\",\n\t\t\tstdout: Buffer.from(redactSensitiveTextForced(result.stdout.toString(\"utf8\"))).subarray(0, 32768),\n\t\t\tstderr: Buffer.from(redactSensitiveTextForced(result.stderr.toString(\"utf8\"))).subarray(0, 32768),\n\t\t},\n\t\t...disposition(result),\n\t});\n\tpublishObject(join(runPath, \"receipts\", `${receipt.envelope.coreSha256}.json`), receipt);\n\treturn receipt.envelope.coreSha256;\n}\n\nexport function readCheckReceipts(\n\trunPath: string,\n\tcontract: RunContract,\n\tbinding: {\n\t\treadonly manifest: CandidateManifest;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): readonly EvidenceReceipt[] {\n\tconst workspace = fingerprint(binding.manifest);\n\treturn Object.freeze(\n\t\tbinding.checks.map((observation) => {\n\t\t\tconst digest = observation.receiptCoreDigest;\n\t\t\tif (!digest || !/^[a-f0-9]{64}$/.test(digest)) throw new VerifiedRunError(\"integrity\");\n\t\t\tconst receipt = validateEvidenceReceipt(readJson(join(runPath, \"receipts\", `${digest}.json`), 8388608));\n\t\t\tconst core = receipt.core;\n\t\t\tconst check = contract.checks.find((item) => item.claimId === observation.claimId);\n\t\t\tconst expected = disposition(observation);\n\t\t\tif (\n\t\t\t\t!check ||\n\t\t\t\tcanonicalJson(receipt.envelope) !== canonicalJson({ coreSha256: digest }) ||\n\t\t\t\tcore.receiptId !== observation.executionId ||\n\t\t\t\tcore.toolCallId !== observation.executionId ||\n\t\t\t\tcore.goalId !== contract.runId ||\n\t\t\t\tcore.executor !== \"internal\" ||\n\t\t\t\tcore.claim !== `Exact stdout for ${check.claimId}` ||\n\t\t\t\tcore.cwd !== \"/workspace\" ||\n\t\t\t\tcore.status !== expected.status ||\n\t\t\t\tcore.exitCode !== expected.exitCode ||\n\t\t\t\tcore.timeoutMs === null ||\n\t\t\t\tcore.timeoutMs > contract.budget.verifyMs ||\n\t\t\t\tcanonicalJson(core.command) !== canonicalJson(command(check)) ||\n\t\t\t\tcanonicalJson(core.workspaceBefore) !== canonicalJson(workspace) ||\n\t\t\t\tcanonicalJson(core.workspaceAfter) !== canonicalJson(workspace)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\treturn receipt;\n\t\t}),\n\t);\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type RunContract } from "omk-protocol";
|
|
2
|
+
import { type TaskRecoveryInspection } from "./dag-recovery.ts";
|
|
3
|
+
import { type VerifiedRunEvidence } from "./evidence.ts";
|
|
4
|
+
import { type RecoveryInspection } from "./recovery.ts";
|
|
5
|
+
import type { RunProjection } from "./run-types.ts";
|
|
6
|
+
import type { VerifiedRunRuntime } from "./session-port.ts";
|
|
7
|
+
import { type WriterRecoveryInspection } from "./writer-recovery.ts";
|
|
8
|
+
export interface VerifiedRunApproval {
|
|
9
|
+
/** Trusted host grant, not a JSON field in the model-authored contract or command. */
|
|
10
|
+
readonly approvedContractDigest: string;
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
export interface VerifiedRunPlan {
|
|
14
|
+
readonly profile: RunContract["profile"];
|
|
15
|
+
readonly contractDigest: string;
|
|
16
|
+
readonly baseDigest: string;
|
|
17
|
+
readonly baseMatches: boolean;
|
|
18
|
+
readonly environmentDigest: string;
|
|
19
|
+
readonly checks: readonly string[];
|
|
20
|
+
readonly executionRequested: false;
|
|
21
|
+
}
|
|
22
|
+
export declare function planVerifiedRun(input: unknown): VerifiedRunPlan;
|
|
23
|
+
/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */
|
|
24
|
+
export declare class RunCoordinator {
|
|
25
|
+
private readonly stateRoot;
|
|
26
|
+
private readonly runtime;
|
|
27
|
+
constructor(stateRoot: string, runtime?: VerifiedRunRuntime);
|
|
28
|
+
inspect(runId: string): RunProjection;
|
|
29
|
+
inspectRecovery(runId: string): RecoveryInspection;
|
|
30
|
+
inspectWriterRecovery(runId: string): WriterRecoveryInspection;
|
|
31
|
+
inspectTaskRecovery(runId: string): TaskRecoveryInspection;
|
|
32
|
+
retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
33
|
+
evidence(runId: string): VerifiedRunEvidence;
|
|
34
|
+
artifact(runId: string, candidateDigest: string, path: string): Buffer;
|
|
35
|
+
resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
36
|
+
restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
37
|
+
start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,cAAc,CAAC;AAMtB,OAAO,EAAsC,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EAAoC,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG3F,OAAO,EAAsB,KAAK,kBAAkB,EAAyB,MAAM,eAAe,CAAC;AAEnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAY5D,OAAO,EAAgD,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEnH,MAAM,WAAW,mBAAmB;IACnC,sFAAsF;IACtF,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AACD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAY/D;AAED,qGAAqG;AACrG,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,YAAY,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAG1D;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAKpC;IAED,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAKjD;IAED,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,CAK7D;IAED,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAKzD;IAEK,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAKtF;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAW3C;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CASrE;IAEK,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAKlF;IAEK,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAQzF;IAEK,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkEnG;CACD","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n\ttype RunContract,\n} from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { acquireSessionOwnerLeaseSync } from \"../session-owner-lease.ts\";\nimport { commandEnvironmentDigest, probeVerifiedSandbox } from \"./broker.ts\";\nimport { captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { inspectTaskRecovery, retryDagTasks, type TaskRecoveryInspection } from \"./dag-recovery.ts\";\nimport { createRunIssuer, readRunEvidence, type VerifiedRunEvidence } from \"./evidence.ts\";\nimport { journalPath, readRunJournal, VerifiedRunJournal } from \"./journal.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { inspectRunRecovery, type RecoveryInspection, resumeFrozenCandidate } from \"./recovery.ts\";\nimport { anchorRunBudget, readRunClock } from \"./recovery-clock.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport type { VerifiedRunRuntime } from \"./session-port.ts\";\nimport {\n\tassertStateOutsideWorkspace,\n\tdigestBytes,\n\tdigestObject,\n\treadRegularFile,\n\tstateRunPath,\n\tVerifiedRunError,\n} from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\nimport { executeWriter } from \"./writer-phase.ts\";\nimport { inspectWriterRecovery, restartIsolatedWriter, type WriterRecoveryInspection } from \"./writer-recovery.ts\";\n\nexport interface VerifiedRunApproval {\n\t/** Trusted host grant, not a JSON field in the model-authored contract or command. */\n\treadonly approvedContractDigest: string;\n\treadonly signal?: AbortSignal;\n}\nexport interface VerifiedRunPlan {\n\treadonly profile: RunContract[\"profile\"];\n\treadonly contractDigest: string;\n\treadonly baseDigest: string;\n\treadonly baseMatches: boolean;\n\treadonly environmentDigest: string;\n\treadonly checks: readonly string[];\n\treadonly executionRequested: false;\n}\n\nexport function planVerifiedRun(input: unknown): VerifiedRunPlan {\n\tconst contract = parseRunContract(input);\n\tconst snapshot = captureCandidate(contract.workspace.root, contract.budget);\n\treturn Object.freeze({\n\t\tprofile: contract.profile,\n\t\tcontractDigest: digestObject(contract),\n\t\tbaseDigest: snapshot.digest,\n\t\tbaseMatches: snapshot.digest === contract.workspace.baseDigest,\n\t\tenvironmentDigest: commandEnvironmentDigest(contract, \"gated-v1\"),\n\t\tchecks: Object.freeze(contract.checks.map((check) => check.claimId)),\n\t\texecutionRequested: false,\n\t});\n}\n\n/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */\nexport class RunCoordinator {\n\tprivate readonly stateRoot: string;\n\tprivate readonly runtime: VerifiedRunRuntime | undefined;\n\tconstructor(stateRoot: string, runtime?: VerifiedRunRuntime) {\n\t\tthis.stateRoot = resolve(stateRoot);\n\t\tthis.runtime = runtime;\n\t}\n\n\tinspect(runId: string): RunProjection {\n\t\tconst journal = readRunJournal(stateRunPath(this.stateRoot, runId));\n\t\tif (!journal || journal.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (journal.state.receiptDigest) this.evidence(runId);\n\t\treturn journal.state;\n\t}\n\n\tinspectRecovery(runId: string): RecoveryInspection {\n\t\tconst report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectWriterRecovery(runId: string): WriterRecoveryInspection {\n\t\tconst report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectTaskRecovery(runId: string): TaskRecoveryInspection {\n\t\tconst report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tasync retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunTaskRetryCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tevidence(runId: string): VerifiedRunEvidence {\n\t\tconst runPath = stateRunPath(this.stateRoot, runId);\n\t\tconst journal = readRunJournal(runPath);\n\t\tconst first = journal?.records[0]?.event;\n\t\tif (!journal || first?.kind !== \"created\" || first.contract.runId !== runId)\n\t\t\tthrow new VerifiedRunError(\"missing_run\");\n\t\treturn readRunEvidence(\n\t\t\trunPath,\n\t\t\tjournal,\n\t\t\tcommandEnvironmentDigest(first.contract, journal.state.budget ? \"gated-v1\" : \"legacy\"),\n\t\t);\n\t}\n\n\tartifact(runId: string, candidateDigest: string, path: string): Buffer {\n\t\tconst evidence = this.evidence(runId);\n\t\tif (!evidence.verified || candidateDigest !== evidence.candidateDigest)\n\t\t\tthrow new VerifiedRunError(\"candidate_mismatch\");\n\t\tconst file = evidence.manifest.files.find((entry) => entry.path === path);\n\t\tif (!file) throw new VerifiedRunError(\"artifact_scope\");\n\t\tconst bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), \"blobs\", file.digest), file.size);\n\t\tif (digestBytes(bytes) !== file.digest || bytes.length !== file.size) throw new VerifiedRunError(\"integrity\");\n\t\treturn bytes;\n\t}\n\n\tasync resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunResumeCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunWriterRestartCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {\n\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t});\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst began = performance.now();\n\t\tconst clock = readRunClock();\n\t\tconst contract = parseRunContract(input);\n\t\tconst command = parseRunStartCommand(request);\n\t\tconst contractDigest = digestObject(contract);\n\t\tif (approval.approvedContractDigest !== contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tif (command.contractDigest !== contractDigest || command.runId !== contract.runId)\n\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\tif (approval.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tassertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);\n\t\tconst runPath = stateRunPath(this.stateRoot, contract.runId);\n\t\tconst existing = readRunJournal(runPath);\n\t\tif (existing) {\n\t\t\tconst first = existing.records[0]?.event;\n\t\t\tif (\n\t\t\t\tfirst?.kind !== \"created\" ||\n\t\t\t\tdigestObject(first.command) !== digestObject(command) ||\n\t\t\t\tdigestObject(first.contract) !== contractDigest\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\t\treturn this.inspect(contract.runId);\n\t\t}\n\t\tconst base = captureCandidate(contract.workspace.root, contract.budget);\n\t\tif (base.digest !== contract.workspace.baseDigest) throw new VerifiedRunError(\"base_conflict\");\n\t\tconst environmentDigest = commandEnvironmentDigest(contract, \"gated-v1\");\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tensureDurableDirectorySync(runPath);\n\t\tconst owner = acquireSessionOwnerLeaseSync(journalPath(runPath));\n\t\ttry {\n\t\t\tif (readRunJournal(runPath)) throw new VerifiedRunError(\"command_conflict\");\n\t\t\tconst journal = new VerifiedRunJournal(runPath, owner);\n\t\t\tjournal.append({ kind: \"created\", contract, command });\n\t\t\tconst budget = anchorRunBudget(contract.budget, clock);\n\t\t\tjournal.append({ kind: \"budget_anchored\", budget, environmentDigest, driver: \"linux-pidns-gate-v1\" });\n\t\t\tconst context: RunPhaseContext = {\n\t\t\t\trunPath,\n\t\t\t\tcontract,\n\t\t\t\tjournal,\n\t\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcreateRunIssuer(runPath);\n\t\t\t\tstoreCandidate(base, runPath);\n\t\t\t\tjournal.append({ kind: \"input_checkpoint\", digest: base.digest });\n\t\t\t\tconst work = join(runPath, \"writer\");\n\t\t\t\tif (contract.profile !== \"linux-command-dag-v1\") materializeCandidate(base, work);\n\t\t\t\tconst workDeadline = began + contract.budget.workMs;\n\t\t\t\tawait executeWriter(context, {\n\t\t\t\t\tworkspace: work,\n\t\t\t\t\tdeadline: workDeadline,\n\t\t\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t\t\t});\n\t\t\t\tif (journal.state.execution === \"paused\") return this.inspect(contract.runId);\n\t\t\t\tpublishWriterCandidate(context, work, workDeadline);\n\t\t\t\tawait verifyCandidate(context);\n\t\t\t\treturn this.inspect(contract.runId);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof VerifiedRunError && !journal.state.receiptDigest)\n\t\t\t\t\treturn journal.append({ kind: \"failed\", code: error.code });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\towner.release();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { parseRunContract, parseRunResumeCommand, parseRunStartCommand, parseRunTaskRetryCommand, parseRunWriterRestartCommand, } from "omk-protocol";
|
|
4
|
+
import { ensureDurableDirectorySync } from "../durable-file-io.js";
|
|
5
|
+
import { acquireSessionOwnerLeaseSync } from "../session-owner-lease.js";
|
|
6
|
+
import { commandEnvironmentDigest, probeVerifiedSandbox } from "./broker.js";
|
|
7
|
+
import { captureCandidate, materializeCandidate, storeCandidate } from "./candidate.js";
|
|
8
|
+
import { preflightCheckReceipts } from "./check-receipt.js";
|
|
9
|
+
import { inspectTaskRecovery, retryDagTasks } from "./dag-recovery.js";
|
|
10
|
+
import { createRunIssuer, readRunEvidence } from "./evidence.js";
|
|
11
|
+
import { journalPath, readRunJournal, VerifiedRunJournal } from "./journal.js";
|
|
12
|
+
import { inspectRunRecovery, resumeFrozenCandidate } from "./recovery.js";
|
|
13
|
+
import { anchorRunBudget, readRunClock } from "./recovery-clock.js";
|
|
14
|
+
import { assertStateOutsideWorkspace, digestBytes, digestObject, readRegularFile, stateRunPath, VerifiedRunError, } from "./storage.js";
|
|
15
|
+
import { verifyCandidate } from "./verification-phase.js";
|
|
16
|
+
import { publishWriterCandidate } from "./writer-completion.js";
|
|
17
|
+
import { executeWriter } from "./writer-phase.js";
|
|
18
|
+
import { inspectWriterRecovery, restartIsolatedWriter } from "./writer-recovery.js";
|
|
19
|
+
export function planVerifiedRun(input) {
|
|
20
|
+
const contract = parseRunContract(input);
|
|
21
|
+
const snapshot = captureCandidate(contract.workspace.root, contract.budget);
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
profile: contract.profile,
|
|
24
|
+
contractDigest: digestObject(contract),
|
|
25
|
+
baseDigest: snapshot.digest,
|
|
26
|
+
baseMatches: snapshot.digest === contract.workspace.baseDigest,
|
|
27
|
+
environmentDigest: commandEnvironmentDigest(contract, "gated-v1"),
|
|
28
|
+
checks: Object.freeze(contract.checks.map((check) => check.claimId)),
|
|
29
|
+
executionRequested: false,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */
|
|
33
|
+
export class RunCoordinator {
|
|
34
|
+
stateRoot;
|
|
35
|
+
runtime;
|
|
36
|
+
constructor(stateRoot, runtime) {
|
|
37
|
+
this.stateRoot = resolve(stateRoot);
|
|
38
|
+
this.runtime = runtime;
|
|
39
|
+
}
|
|
40
|
+
inspect(runId) {
|
|
41
|
+
const journal = readRunJournal(stateRunPath(this.stateRoot, runId));
|
|
42
|
+
if (!journal || journal.state.runId !== runId)
|
|
43
|
+
throw new VerifiedRunError("missing_run");
|
|
44
|
+
if (journal.state.receiptDigest)
|
|
45
|
+
this.evidence(runId);
|
|
46
|
+
return journal.state;
|
|
47
|
+
}
|
|
48
|
+
inspectRecovery(runId) {
|
|
49
|
+
const report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));
|
|
50
|
+
if (report.state.runId !== runId)
|
|
51
|
+
throw new VerifiedRunError("missing_run");
|
|
52
|
+
if (report.state.receiptDigest)
|
|
53
|
+
this.evidence(runId);
|
|
54
|
+
return report;
|
|
55
|
+
}
|
|
56
|
+
inspectWriterRecovery(runId) {
|
|
57
|
+
const report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));
|
|
58
|
+
if (report.state.runId !== runId)
|
|
59
|
+
throw new VerifiedRunError("missing_run");
|
|
60
|
+
if (report.state.receiptDigest)
|
|
61
|
+
this.evidence(runId);
|
|
62
|
+
return report;
|
|
63
|
+
}
|
|
64
|
+
inspectTaskRecovery(runId) {
|
|
65
|
+
const report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));
|
|
66
|
+
if (report.state.runId !== runId)
|
|
67
|
+
throw new VerifiedRunError("missing_run");
|
|
68
|
+
if (report.state.receiptDigest)
|
|
69
|
+
this.evidence(runId);
|
|
70
|
+
return report;
|
|
71
|
+
}
|
|
72
|
+
async retryTasks(input, approval) {
|
|
73
|
+
const command = parseRunTaskRetryCommand(input);
|
|
74
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
75
|
+
throw new VerifiedRunError("approval");
|
|
76
|
+
await retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);
|
|
77
|
+
return this.inspect(command.runId);
|
|
78
|
+
}
|
|
79
|
+
evidence(runId) {
|
|
80
|
+
const runPath = stateRunPath(this.stateRoot, runId);
|
|
81
|
+
const journal = readRunJournal(runPath);
|
|
82
|
+
const first = journal?.records[0]?.event;
|
|
83
|
+
if (!journal || first?.kind !== "created" || first.contract.runId !== runId)
|
|
84
|
+
throw new VerifiedRunError("missing_run");
|
|
85
|
+
return readRunEvidence(runPath, journal, commandEnvironmentDigest(first.contract, journal.state.budget ? "gated-v1" : "legacy"));
|
|
86
|
+
}
|
|
87
|
+
artifact(runId, candidateDigest, path) {
|
|
88
|
+
const evidence = this.evidence(runId);
|
|
89
|
+
if (!evidence.verified || candidateDigest !== evidence.candidateDigest)
|
|
90
|
+
throw new VerifiedRunError("candidate_mismatch");
|
|
91
|
+
const file = evidence.manifest.files.find((entry) => entry.path === path);
|
|
92
|
+
if (!file)
|
|
93
|
+
throw new VerifiedRunError("artifact_scope");
|
|
94
|
+
const bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), "blobs", file.digest), file.size);
|
|
95
|
+
if (digestBytes(bytes) !== file.digest || bytes.length !== file.size)
|
|
96
|
+
throw new VerifiedRunError("integrity");
|
|
97
|
+
return bytes;
|
|
98
|
+
}
|
|
99
|
+
async resume(input, approval) {
|
|
100
|
+
const command = parseRunResumeCommand(input);
|
|
101
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
102
|
+
throw new VerifiedRunError("approval");
|
|
103
|
+
await resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);
|
|
104
|
+
return this.inspect(command.runId);
|
|
105
|
+
}
|
|
106
|
+
async restartWriter(input, approval) {
|
|
107
|
+
const command = parseRunWriterRestartCommand(input);
|
|
108
|
+
if (approval.approvedContractDigest !== command.contractDigest)
|
|
109
|
+
throw new VerifiedRunError("approval");
|
|
110
|
+
await restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {
|
|
111
|
+
...(approval.signal ? { signal: approval.signal } : {}),
|
|
112
|
+
...(this.runtime ? { runtime: this.runtime } : {}),
|
|
113
|
+
});
|
|
114
|
+
return this.inspect(command.runId);
|
|
115
|
+
}
|
|
116
|
+
async start(input, request, approval) {
|
|
117
|
+
const began = performance.now();
|
|
118
|
+
const clock = readRunClock();
|
|
119
|
+
const contract = parseRunContract(input);
|
|
120
|
+
const command = parseRunStartCommand(request);
|
|
121
|
+
const contractDigest = digestObject(contract);
|
|
122
|
+
if (approval.approvedContractDigest !== contractDigest)
|
|
123
|
+
throw new VerifiedRunError("approval");
|
|
124
|
+
if (command.contractDigest !== contractDigest || command.runId !== contract.runId)
|
|
125
|
+
throw new VerifiedRunError("command_conflict");
|
|
126
|
+
if (approval.signal?.aborted)
|
|
127
|
+
throw new VerifiedRunError("cancelled");
|
|
128
|
+
assertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);
|
|
129
|
+
const runPath = stateRunPath(this.stateRoot, contract.runId);
|
|
130
|
+
const existing = readRunJournal(runPath);
|
|
131
|
+
if (existing) {
|
|
132
|
+
const first = existing.records[0]?.event;
|
|
133
|
+
if (first?.kind !== "created" ||
|
|
134
|
+
digestObject(first.command) !== digestObject(command) ||
|
|
135
|
+
digestObject(first.contract) !== contractDigest)
|
|
136
|
+
throw new VerifiedRunError("command_conflict");
|
|
137
|
+
return this.inspect(contract.runId);
|
|
138
|
+
}
|
|
139
|
+
const base = captureCandidate(contract.workspace.root, contract.budget);
|
|
140
|
+
if (base.digest !== contract.workspace.baseDigest)
|
|
141
|
+
throw new VerifiedRunError("base_conflict");
|
|
142
|
+
const environmentDigest = commandEnvironmentDigest(contract, "gated-v1");
|
|
143
|
+
preflightCheckReceipts(contract);
|
|
144
|
+
probeVerifiedSandbox();
|
|
145
|
+
ensureDurableDirectorySync(runPath);
|
|
146
|
+
const owner = acquireSessionOwnerLeaseSync(journalPath(runPath));
|
|
147
|
+
try {
|
|
148
|
+
if (readRunJournal(runPath))
|
|
149
|
+
throw new VerifiedRunError("command_conflict");
|
|
150
|
+
const journal = new VerifiedRunJournal(runPath, owner);
|
|
151
|
+
journal.append({ kind: "created", contract, command });
|
|
152
|
+
const budget = anchorRunBudget(contract.budget, clock);
|
|
153
|
+
journal.append({ kind: "budget_anchored", budget, environmentDigest, driver: "linux-pidns-gate-v1" });
|
|
154
|
+
const context = {
|
|
155
|
+
runPath,
|
|
156
|
+
contract,
|
|
157
|
+
journal,
|
|
158
|
+
...(approval.signal ? { signal: approval.signal } : {}),
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
createRunIssuer(runPath);
|
|
162
|
+
storeCandidate(base, runPath);
|
|
163
|
+
journal.append({ kind: "input_checkpoint", digest: base.digest });
|
|
164
|
+
const work = join(runPath, "writer");
|
|
165
|
+
if (contract.profile !== "linux-command-dag-v1")
|
|
166
|
+
materializeCandidate(base, work);
|
|
167
|
+
const workDeadline = began + contract.budget.workMs;
|
|
168
|
+
await executeWriter(context, {
|
|
169
|
+
workspace: work,
|
|
170
|
+
deadline: workDeadline,
|
|
171
|
+
...(this.runtime ? { runtime: this.runtime } : {}),
|
|
172
|
+
});
|
|
173
|
+
if (journal.state.execution === "paused")
|
|
174
|
+
return this.inspect(contract.runId);
|
|
175
|
+
publishWriterCandidate(context, work, workDeadline);
|
|
176
|
+
await verifyCandidate(context);
|
|
177
|
+
return this.inspect(contract.runId);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (error instanceof VerifiedRunError && !journal.state.receiptDigest)
|
|
181
|
+
return journal.append({ kind: "failed", code: error.code });
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
owner.release();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../src/core/verified-run/coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,4BAA4B,GAE5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAA+B,MAAM,mBAAmB,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,eAAe,EAA4B,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE/E,OAAO,EAAE,kBAAkB,EAA2B,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGpE,OAAO,EACN,2BAA2B,EAC3B,WAAW,EACX,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAiC,MAAM,sBAAsB,CAAC;AAiBnH,MAAM,UAAU,eAAe,CAAC,KAAc,EAAmB;IAChE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,cAAc,EAAE,YAAY,CAAC,QAAQ,CAAC;QACtC,UAAU,EAAE,QAAQ,CAAC,MAAM;QAC3B,WAAW,EAAE,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,SAAS,CAAC,UAAU;QAC9D,iBAAiB,EAAE,wBAAwB,CAAC,QAAQ,EAAE,UAAU,CAAC;QACjE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpE,kBAAkB,EAAE,KAAK;KACzB,CAAC,CAAC;AAAA,CACH;AAED,qGAAqG;AACrG,MAAM,OAAO,cAAc;IACT,SAAS,CAAS;IAClB,OAAO,CAAiC;IACzD,YAAY,SAAiB,EAAE,OAA4B,EAAE;QAC5D,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAAA,CACvB;IAED,OAAO,CAAC,KAAa,EAAiB;QACrC,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QACzF,IAAI,OAAO,CAAC,KAAK,CAAC,aAAa;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO,OAAO,CAAC,KAAK,CAAC;IAAA,CACrB;IAED,eAAe,CAAC,KAAa,EAAsB;QAClD,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAAA,CACd;IAED,qBAAqB,CAAC,KAAa,EAA4B;QAC9D,MAAM,MAAM,GAAG,qBAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1E,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAAA,CACd;IAED,mBAAmB,CAAC,KAAa,EAA0B;QAC1D,MAAM,MAAM,GAAG,mBAAmB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAAA,CACd;IAED,KAAK,CAAC,UAAU,CAAC,KAAc,EAAE,QAA6B,EAA0B;QACvF,MAAM,OAAO,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,QAAQ,CAAC,sBAAsB,KAAK,OAAO,CAAC,cAAc;YAAE,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACvG,MAAM,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAAA,CACnC;IAED,QAAQ,CAAC,KAAa,EAAuB;QAC5C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;QACzC,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAK,KAAK;YAC1E,MAAM,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC3C,OAAO,eAAe,CACrB,OAAO,EACP,OAAO,EACP,wBAAwB,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CACtF,CAAC;IAAA,CACF;IAED,QAAQ,CAAC,KAAa,EAAE,eAAuB,EAAE,IAAY,EAAU;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,eAAe,KAAK,QAAQ,CAAC,eAAe;YACrE,MAAM,IAAI,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1G,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC9G,OAAO,KAAK,CAAC;IAAA,CACb;IAED,KAAK,CAAC,MAAM,CAAC,KAAc,EAAE,QAA6B,EAA0B;QACnF,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,sBAAsB,KAAK,OAAO,CAAC,cAAc;YAAE,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACvG,MAAM,qBAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnG,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAAA,CACnC;IAED,KAAK,CAAC,aAAa,CAAC,KAAc,EAAE,QAA6B,EAA0B;QAC1F,MAAM,OAAO,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,QAAQ,CAAC,sBAAsB,KAAK,OAAO,CAAC,cAAc;YAAE,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACvG,MAAM,qBAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE;YACjF,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAAA,CACnC;IAED,KAAK,CAAC,KAAK,CAAC,KAAc,EAAE,OAAgB,EAAE,QAA6B,EAA0B;QACpG,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,cAAc,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,sBAAsB,KAAK,cAAc;YAAE,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC/F,IAAI,OAAO,CAAC,cAAc,KAAK,cAAc,IAAI,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK;YAChF,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;QAChD,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtE,2BAA2B,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACzC,IAAI,QAAQ,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;YACzC,IACC,KAAK,EAAE,IAAI,KAAK,SAAS;gBACzB,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,YAAY,CAAC,OAAO,CAAC;gBACrD,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,cAAc;gBAE/C,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,SAAS,CAAC,UAAU;YAAE,MAAM,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAC/F,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACzE,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACjC,oBAAoB,EAAE,CAAC;QACvB,0BAA0B,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,4BAA4B,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC;YACJ,IAAI,cAAc,CAAC,OAAO,CAAC;gBAAE,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;YAC5E,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACvD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACtG,MAAM,OAAO,GAAoB;gBAChC,OAAO;gBACP,QAAQ;gBACR,OAAO;gBACP,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvD,CAAC;YACF,IAAI,CAAC;gBACJ,eAAe,CAAC,OAAO,CAAC,CAAC;gBACzB,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC9B,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAClE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACrC,IAAI,QAAQ,CAAC,OAAO,KAAK,sBAAsB;oBAAE,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAClF,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;gBACpD,MAAM,aAAa,CAAC,OAAO,EAAE;oBAC5B,SAAS,EAAE,IAAI;oBACf,QAAQ,EAAE,YAAY;oBACtB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAClD,CAAC,CAAC;gBACH,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9E,sBAAsB,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;gBACpD,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAI,KAAK,YAAY,gBAAgB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa;oBACpE,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC7D,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,KAAK,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IAAA,CACD;CACD","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n\ttype RunContract,\n} from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { acquireSessionOwnerLeaseSync } from \"../session-owner-lease.ts\";\nimport { commandEnvironmentDigest, probeVerifiedSandbox } from \"./broker.ts\";\nimport { captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { inspectTaskRecovery, retryDagTasks, type TaskRecoveryInspection } from \"./dag-recovery.ts\";\nimport { createRunIssuer, readRunEvidence, type VerifiedRunEvidence } from \"./evidence.ts\";\nimport { journalPath, readRunJournal, VerifiedRunJournal } from \"./journal.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { inspectRunRecovery, type RecoveryInspection, resumeFrozenCandidate } from \"./recovery.ts\";\nimport { anchorRunBudget, readRunClock } from \"./recovery-clock.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport type { VerifiedRunRuntime } from \"./session-port.ts\";\nimport {\n\tassertStateOutsideWorkspace,\n\tdigestBytes,\n\tdigestObject,\n\treadRegularFile,\n\tstateRunPath,\n\tVerifiedRunError,\n} from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\nimport { executeWriter } from \"./writer-phase.ts\";\nimport { inspectWriterRecovery, restartIsolatedWriter, type WriterRecoveryInspection } from \"./writer-recovery.ts\";\n\nexport interface VerifiedRunApproval {\n\t/** Trusted host grant, not a JSON field in the model-authored contract or command. */\n\treadonly approvedContractDigest: string;\n\treadonly signal?: AbortSignal;\n}\nexport interface VerifiedRunPlan {\n\treadonly profile: RunContract[\"profile\"];\n\treadonly contractDigest: string;\n\treadonly baseDigest: string;\n\treadonly baseMatches: boolean;\n\treadonly environmentDigest: string;\n\treadonly checks: readonly string[];\n\treadonly executionRequested: false;\n}\n\nexport function planVerifiedRun(input: unknown): VerifiedRunPlan {\n\tconst contract = parseRunContract(input);\n\tconst snapshot = captureCandidate(contract.workspace.root, contract.budget);\n\treturn Object.freeze({\n\t\tprofile: contract.profile,\n\t\tcontractDigest: digestObject(contract),\n\t\tbaseDigest: snapshot.digest,\n\t\tbaseMatches: snapshot.digest === contract.workspace.baseDigest,\n\t\tenvironmentDigest: commandEnvironmentDigest(contract, \"gated-v1\"),\n\t\tchecks: Object.freeze(contract.checks.map((check) => check.claimId)),\n\t\texecutionRequested: false,\n\t});\n}\n\n/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */\nexport class RunCoordinator {\n\tprivate readonly stateRoot: string;\n\tprivate readonly runtime: VerifiedRunRuntime | undefined;\n\tconstructor(stateRoot: string, runtime?: VerifiedRunRuntime) {\n\t\tthis.stateRoot = resolve(stateRoot);\n\t\tthis.runtime = runtime;\n\t}\n\n\tinspect(runId: string): RunProjection {\n\t\tconst journal = readRunJournal(stateRunPath(this.stateRoot, runId));\n\t\tif (!journal || journal.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (journal.state.receiptDigest) this.evidence(runId);\n\t\treturn journal.state;\n\t}\n\n\tinspectRecovery(runId: string): RecoveryInspection {\n\t\tconst report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectWriterRecovery(runId: string): WriterRecoveryInspection {\n\t\tconst report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectTaskRecovery(runId: string): TaskRecoveryInspection {\n\t\tconst report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tasync retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunTaskRetryCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tevidence(runId: string): VerifiedRunEvidence {\n\t\tconst runPath = stateRunPath(this.stateRoot, runId);\n\t\tconst journal = readRunJournal(runPath);\n\t\tconst first = journal?.records[0]?.event;\n\t\tif (!journal || first?.kind !== \"created\" || first.contract.runId !== runId)\n\t\t\tthrow new VerifiedRunError(\"missing_run\");\n\t\treturn readRunEvidence(\n\t\t\trunPath,\n\t\t\tjournal,\n\t\t\tcommandEnvironmentDigest(first.contract, journal.state.budget ? \"gated-v1\" : \"legacy\"),\n\t\t);\n\t}\n\n\tartifact(runId: string, candidateDigest: string, path: string): Buffer {\n\t\tconst evidence = this.evidence(runId);\n\t\tif (!evidence.verified || candidateDigest !== evidence.candidateDigest)\n\t\t\tthrow new VerifiedRunError(\"candidate_mismatch\");\n\t\tconst file = evidence.manifest.files.find((entry) => entry.path === path);\n\t\tif (!file) throw new VerifiedRunError(\"artifact_scope\");\n\t\tconst bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), \"blobs\", file.digest), file.size);\n\t\tif (digestBytes(bytes) !== file.digest || bytes.length !== file.size) throw new VerifiedRunError(\"integrity\");\n\t\treturn bytes;\n\t}\n\n\tasync resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunResumeCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunWriterRestartCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {\n\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t});\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst began = performance.now();\n\t\tconst clock = readRunClock();\n\t\tconst contract = parseRunContract(input);\n\t\tconst command = parseRunStartCommand(request);\n\t\tconst contractDigest = digestObject(contract);\n\t\tif (approval.approvedContractDigest !== contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tif (command.contractDigest !== contractDigest || command.runId !== contract.runId)\n\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\tif (approval.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tassertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);\n\t\tconst runPath = stateRunPath(this.stateRoot, contract.runId);\n\t\tconst existing = readRunJournal(runPath);\n\t\tif (existing) {\n\t\t\tconst first = existing.records[0]?.event;\n\t\t\tif (\n\t\t\t\tfirst?.kind !== \"created\" ||\n\t\t\t\tdigestObject(first.command) !== digestObject(command) ||\n\t\t\t\tdigestObject(first.contract) !== contractDigest\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\t\treturn this.inspect(contract.runId);\n\t\t}\n\t\tconst base = captureCandidate(contract.workspace.root, contract.budget);\n\t\tif (base.digest !== contract.workspace.baseDigest) throw new VerifiedRunError(\"base_conflict\");\n\t\tconst environmentDigest = commandEnvironmentDigest(contract, \"gated-v1\");\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tensureDurableDirectorySync(runPath);\n\t\tconst owner = acquireSessionOwnerLeaseSync(journalPath(runPath));\n\t\ttry {\n\t\t\tif (readRunJournal(runPath)) throw new VerifiedRunError(\"command_conflict\");\n\t\t\tconst journal = new VerifiedRunJournal(runPath, owner);\n\t\t\tjournal.append({ kind: \"created\", contract, command });\n\t\t\tconst budget = anchorRunBudget(contract.budget, clock);\n\t\t\tjournal.append({ kind: \"budget_anchored\", budget, environmentDigest, driver: \"linux-pidns-gate-v1\" });\n\t\t\tconst context: RunPhaseContext = {\n\t\t\t\trunPath,\n\t\t\t\tcontract,\n\t\t\t\tjournal,\n\t\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcreateRunIssuer(runPath);\n\t\t\t\tstoreCandidate(base, runPath);\n\t\t\t\tjournal.append({ kind: \"input_checkpoint\", digest: base.digest });\n\t\t\t\tconst work = join(runPath, \"writer\");\n\t\t\t\tif (contract.profile !== \"linux-command-dag-v1\") materializeCandidate(base, work);\n\t\t\t\tconst workDeadline = began + contract.budget.workMs;\n\t\t\t\tawait executeWriter(context, {\n\t\t\t\t\tworkspace: work,\n\t\t\t\t\tdeadline: workDeadline,\n\t\t\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t\t\t});\n\t\t\t\tif (journal.state.execution === \"paused\") return this.inspect(contract.runId);\n\t\t\t\tpublishWriterCandidate(context, work, workDeadline);\n\t\t\t\tawait verifyCandidate(context);\n\t\t\t\treturn this.inspect(contract.runId);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof VerifiedRunError && !journal.state.receiptDigest)\n\t\t\t\t\treturn journal.append({ kind: \"failed\", code: error.code });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\towner.release();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RunDagTask } from "omk-protocol";
|
|
2
|
+
import { type CandidateSnapshot } from "./candidate.ts";
|
|
3
|
+
import type { RunPhaseContext } from "./phase-context.ts";
|
|
4
|
+
/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */
|
|
5
|
+
export declare function composeDagCandidate(context: Pick<RunPhaseContext, "runPath" | "contract"> & {
|
|
6
|
+
readonly journal: Pick<RunPhaseContext["journal"], "state">;
|
|
7
|
+
}, selected: readonly RunDagTask[]): CandidateSnapshot;
|
|
8
|
+
//# sourceMappingURL=dag-candidates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-candidates.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAsB,KAAK,iBAAiB,EAAiB,MAAM,gBAAgB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAa1D,mGAAmG;AACnG,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG;IACxD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;CAC5D,EACD,QAAQ,EAAE,SAAS,UAAU,EAAE,GAC7B,iBAAiB,CA0CnB","sourcesContent":["import type { RunDagTask } from \"omk-protocol\";\nimport { type CandidateFile, type CandidateSnapshot, loadCandidate } from \"./candidate.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\n// Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).\nfunction treeOrder(left: string, right: string): number {\n\tconst a = left.split(\"/\");\n\tconst b = right.split(\"/\");\n\tfor (let index = 0; index < Math.min(a.length, b.length); index++) {\n\t\tif (a[index] !== b[index]) return a[index] < b[index] ? -1 : 1;\n\t}\n\treturn a.length - b.length;\n}\n\n/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */\nexport function composeDagCandidate(\n\tcontext: Pick<RunPhaseContext, \"runPath\" | \"contract\"> & {\n\t\treadonly journal: Pick<RunPhaseContext[\"journal\"], \"state\">;\n\t},\n\tselected: readonly RunDagTask[],\n): CandidateSnapshot {\n\tconst { contract, journal, runPath } = context;\n\tif (!journal.state.inputDigest) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);\n\tconst files = new Map<string, CandidateFile>(base.manifest.files.map((file) => [file.path, file]));\n\tconst directories = new Set(base.manifest.directories);\n\tconst blobs = new Map(base.contents);\n\tfor (const definition of selected) {\n\t\tconst task = journal.state.tasks.find((task) => task.taskId === definition.id);\n\t\tif (task?.status !== \"succeeded\") throw new VerifiedRunError(\"task_not_ready\");\n\t\tconst output = loadCandidate(runPath, task.outputDigest, contract.budget);\n\t\tconst owned = (path: string): boolean =>\n\t\t\tdefinition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));\n\t\tfor (const path of files.keys()) if (owned(path)) files.delete(path);\n\t\tfor (const path of directories) if (owned(path)) directories.delete(path);\n\t\tfor (const path of output.manifest.directories) if (owned(path)) directories.add(path);\n\t\tfor (const file of output.manifest.files) {\n\t\t\tif (!owned(file.path)) continue;\n\t\t\tconst bytes = output.contents.get(file.digest);\n\t\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\t\tfiles.set(file.path, file);\n\t\t\tblobs.set(file.digest, bytes);\n\t\t}\n\t}\n\tconst entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));\n\tif (\n\t\tentries.length + directories.size > contract.budget.maxFiles ||\n\t\tentries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes\n\t)\n\t\tthrow new VerifiedRunError(\"storage_limit\");\n\tconst manifest = Object.freeze({\n\t\tversion: 1 as const,\n\t\tdirectories: Object.freeze([...directories].sort(treeOrder)),\n\t\tfiles: Object.freeze(entries),\n\t});\n\tconst contents = new Map<string, Buffer>();\n\tfor (const file of entries) {\n\t\tconst bytes = blobs.get(file.digest);\n\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\tcontents.set(file.digest, bytes);\n\t}\n\treturn { manifest, digest: digestObject(manifest), contents };\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { loadCandidate } from "./candidate.js";
|
|
2
|
+
import { digestObject, VerifiedRunError } from "./storage.js";
|
|
3
|
+
// Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).
|
|
4
|
+
function treeOrder(left, right) {
|
|
5
|
+
const a = left.split("/");
|
|
6
|
+
const b = right.split("/");
|
|
7
|
+
for (let index = 0; index < Math.min(a.length, b.length); index++) {
|
|
8
|
+
if (a[index] !== b[index])
|
|
9
|
+
return a[index] < b[index] ? -1 : 1;
|
|
10
|
+
}
|
|
11
|
+
return a.length - b.length;
|
|
12
|
+
}
|
|
13
|
+
/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */
|
|
14
|
+
export function composeDagCandidate(context, selected) {
|
|
15
|
+
const { contract, journal, runPath } = context;
|
|
16
|
+
if (!journal.state.inputDigest)
|
|
17
|
+
throw new VerifiedRunError("input_checkpoint_missing");
|
|
18
|
+
const base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);
|
|
19
|
+
const files = new Map(base.manifest.files.map((file) => [file.path, file]));
|
|
20
|
+
const directories = new Set(base.manifest.directories);
|
|
21
|
+
const blobs = new Map(base.contents);
|
|
22
|
+
for (const definition of selected) {
|
|
23
|
+
const task = journal.state.tasks.find((task) => task.taskId === definition.id);
|
|
24
|
+
if (task?.status !== "succeeded")
|
|
25
|
+
throw new VerifiedRunError("task_not_ready");
|
|
26
|
+
const output = loadCandidate(runPath, task.outputDigest, contract.budget);
|
|
27
|
+
const owned = (path) => definition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));
|
|
28
|
+
for (const path of files.keys())
|
|
29
|
+
if (owned(path))
|
|
30
|
+
files.delete(path);
|
|
31
|
+
for (const path of directories)
|
|
32
|
+
if (owned(path))
|
|
33
|
+
directories.delete(path);
|
|
34
|
+
for (const path of output.manifest.directories)
|
|
35
|
+
if (owned(path))
|
|
36
|
+
directories.add(path);
|
|
37
|
+
for (const file of output.manifest.files) {
|
|
38
|
+
if (!owned(file.path))
|
|
39
|
+
continue;
|
|
40
|
+
const bytes = output.contents.get(file.digest);
|
|
41
|
+
if (!bytes)
|
|
42
|
+
throw new VerifiedRunError("integrity");
|
|
43
|
+
files.set(file.path, file);
|
|
44
|
+
blobs.set(file.digest, bytes);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));
|
|
48
|
+
if (entries.length + directories.size > contract.budget.maxFiles ||
|
|
49
|
+
entries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes)
|
|
50
|
+
throw new VerifiedRunError("storage_limit");
|
|
51
|
+
const manifest = Object.freeze({
|
|
52
|
+
version: 1,
|
|
53
|
+
directories: Object.freeze([...directories].sort(treeOrder)),
|
|
54
|
+
files: Object.freeze(entries),
|
|
55
|
+
});
|
|
56
|
+
const contents = new Map();
|
|
57
|
+
for (const file of entries) {
|
|
58
|
+
const bytes = blobs.get(file.digest);
|
|
59
|
+
if (!bytes)
|
|
60
|
+
throw new VerifiedRunError("integrity");
|
|
61
|
+
contents.set(file.digest, bytes);
|
|
62
|
+
}
|
|
63
|
+
return { manifest, digest: digestObject(manifest), contents };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=dag-candidates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-candidates.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-candidates.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RunDagTask } from \"omk-protocol\";\nimport { type CandidateFile, type CandidateSnapshot, loadCandidate } from \"./candidate.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\n// Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).\nfunction treeOrder(left: string, right: string): number {\n\tconst a = left.split(\"/\");\n\tconst b = right.split(\"/\");\n\tfor (let index = 0; index < Math.min(a.length, b.length); index++) {\n\t\tif (a[index] !== b[index]) return a[index] < b[index] ? -1 : 1;\n\t}\n\treturn a.length - b.length;\n}\n\n/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */\nexport function composeDagCandidate(\n\tcontext: Pick<RunPhaseContext, \"runPath\" | \"contract\"> & {\n\t\treadonly journal: Pick<RunPhaseContext[\"journal\"], \"state\">;\n\t},\n\tselected: readonly RunDagTask[],\n): CandidateSnapshot {\n\tconst { contract, journal, runPath } = context;\n\tif (!journal.state.inputDigest) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);\n\tconst files = new Map<string, CandidateFile>(base.manifest.files.map((file) => [file.path, file]));\n\tconst directories = new Set(base.manifest.directories);\n\tconst blobs = new Map(base.contents);\n\tfor (const definition of selected) {\n\t\tconst task = journal.state.tasks.find((task) => task.taskId === definition.id);\n\t\tif (task?.status !== \"succeeded\") throw new VerifiedRunError(\"task_not_ready\");\n\t\tconst output = loadCandidate(runPath, task.outputDigest, contract.budget);\n\t\tconst owned = (path: string): boolean =>\n\t\t\tdefinition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));\n\t\tfor (const path of files.keys()) if (owned(path)) files.delete(path);\n\t\tfor (const path of directories) if (owned(path)) directories.delete(path);\n\t\tfor (const path of output.manifest.directories) if (owned(path)) directories.add(path);\n\t\tfor (const file of output.manifest.files) {\n\t\t\tif (!owned(file.path)) continue;\n\t\t\tconst bytes = output.contents.get(file.digest);\n\t\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\t\tfiles.set(file.path, file);\n\t\t\tblobs.set(file.digest, bytes);\n\t\t}\n\t}\n\tconst entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));\n\tif (\n\t\tentries.length + directories.size > contract.budget.maxFiles ||\n\t\tentries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes\n\t)\n\t\tthrow new VerifiedRunError(\"storage_limit\");\n\tconst manifest = Object.freeze({\n\t\tversion: 1 as const,\n\t\tdirectories: Object.freeze([...directories].sort(treeOrder)),\n\t\tfiles: Object.freeze(entries),\n\t});\n\tconst contents = new Map<string, Buffer>();\n\tfor (const file of entries) {\n\t\tconst bytes = blobs.get(file.digest);\n\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\tcontents.set(file.digest, bytes);\n\t}\n\treturn { manifest, digest: digestObject(manifest), contents };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RunPhaseContext } from "./phase-context.ts";
|
|
2
|
+
/** Deliberately one child at a time: all ownership and process fencing still use the existing broker. */
|
|
3
|
+
export declare function executeDag(context: RunPhaseContext, options: {
|
|
4
|
+
readonly workspace: string;
|
|
5
|
+
readonly deadline: number;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=dag-phase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-phase.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-phase.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAiE1D,yGAAyG;AACzG,wBAAsB,UAAU,CAC/B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,IAAI,CAAC,CAmBf","sourcesContent":["import { join } from \"node:path\";\nimport { orderRunDag, type RunDagTask, runDagAncestors } from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport { executeRunCommand } from \"./owned-execution.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction observeWork(context: RunPhaseContext): number {\n\tconst budget = context.journal.state.budget;\n\tif (!budget) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst clock = readRunClock();\n\tif (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0) throw new VerifiedRunError(\"deadline\");\n\treturn clock.nowMs;\n}\n\nasync function executeTask(context: RunPhaseContext, task: RunDagTask, deadline: number): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tif (context.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst previous = journal.state.tasks.find((item) => item.taskId === task.id);\n\tif (previous?.status !== \"pending\") throw new VerifiedRunError(\"task_not_ready\");\n\tconst attempt = previous.attempt + 1;\n\tconst argv = task.attempts[previous.attempt];\n\tif (!argv) throw new VerifiedRunError(\"task_attempt_limit\");\n\tconst input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));\n\tstoreCandidate(input, runPath);\n\tconst workspace = join(runPath, \"tasks\", `${task.id}-${attempt}-g${journal.state.generation}`);\n\tmaterializeCandidate(input, workspace);\n\tjournal.append({\n\t\tkind: \"task_started\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\tinputDigest: input.digest,\n\t\tobservedMs: observeWork(context),\n\t});\n\tconst { result } = await executeRunCommand(\n\t\tjournal,\n\t\t{ role: \"writer\", argv, workspace, deadline, claimId: null },\n\t\t{ ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) },\n\t);\n\tif (result.failure === \"deadline\" || result.failure === \"cancelled\") throw new VerifiedRunError(result.failure);\n\tlet outputDigest: string | null = null;\n\tlet failure = result.failure;\n\tif (!failure) {\n\t\ttry {\n\t\t\tconst output = captureCandidate(workspace, contract.budget);\n\t\t\tassertCandidateScope(input.manifest, output.manifest, task.writablePaths);\n\t\t\tstoreCandidate(output, runPath);\n\t\t\toutputDigest = output.digest;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\t!(error instanceof VerifiedRunError) ||\n\t\t\t\t![\"scope_changed\", \"file_type\", \"storage_limit\"].includes(error.code)\n\t\t\t)\n\t\t\t\tthrow error;\n\t\t\tfailure = error.code;\n\t\t}\n\t}\n\tjournal.append({\n\t\tkind: \"task_finished\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\toutputDigest,\n\t\tfailure,\n\t\tobservedMs: observeWork(context),\n\t});\n}\n\n/** Deliberately one child at a time: all ownership and process fencing still use the existing broker. */\nexport async function executeDag(\n\tcontext: RunPhaseContext,\n\toptions: { readonly workspace: string; readonly deadline: number },\n): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tensureDurableDirectorySync(join(runPath, \"tasks\"));\n\tconst order = orderRunDag(contract.writer.tasks);\n\tfor (;;) {\n\t\tconst ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));\n\t\tconst next = order.find((task) => ready.has(task.id));\n\t\tif (!next) break;\n\t\tawait executeTask(context, next, options.deadline);\n\t}\n\tif (\n\t\tjournal.state.tasks.some((task) => task.status !== \"succeeded\" || task.generation !== journal.state.generation)\n\t) {\n\t\tjournal.append({ kind: \"tasks_paused\" });\n\t\treturn;\n\t}\n\tobserveWork(context);\n\tmaterializeCandidate(composeDagCandidate(context, order), options.workspace);\n}\n"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { orderRunDag, runDagAncestors } from "omk-protocol";
|
|
3
|
+
import { ensureDurableDirectorySync } from "../durable-file-io.js";
|
|
4
|
+
import { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from "./candidate.js";
|
|
5
|
+
import { composeDagCandidate } from "./dag-candidates.js";
|
|
6
|
+
import { readyDagTasks } from "./dag-projection.js";
|
|
7
|
+
import { executeRunCommand } from "./owned-execution.js";
|
|
8
|
+
import { readRunClock, remainingRunTime } from "./recovery-clock.js";
|
|
9
|
+
import { VerifiedRunError } from "./storage.js";
|
|
10
|
+
function observeWork(context) {
|
|
11
|
+
const budget = context.journal.state.budget;
|
|
12
|
+
if (!budget)
|
|
13
|
+
throw new VerifiedRunError("input_checkpoint_missing");
|
|
14
|
+
const clock = readRunClock();
|
|
15
|
+
if (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0)
|
|
16
|
+
throw new VerifiedRunError("deadline");
|
|
17
|
+
return clock.nowMs;
|
|
18
|
+
}
|
|
19
|
+
async function executeTask(context, task, deadline) {
|
|
20
|
+
const { contract, journal, runPath } = context;
|
|
21
|
+
if (contract.profile !== "linux-command-dag-v1")
|
|
22
|
+
throw new VerifiedRunError("unsupported");
|
|
23
|
+
if (context.signal?.aborted)
|
|
24
|
+
throw new VerifiedRunError("cancelled");
|
|
25
|
+
const previous = journal.state.tasks.find((item) => item.taskId === task.id);
|
|
26
|
+
if (previous?.status !== "pending")
|
|
27
|
+
throw new VerifiedRunError("task_not_ready");
|
|
28
|
+
const attempt = previous.attempt + 1;
|
|
29
|
+
const argv = task.attempts[previous.attempt];
|
|
30
|
+
if (!argv)
|
|
31
|
+
throw new VerifiedRunError("task_attempt_limit");
|
|
32
|
+
const input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));
|
|
33
|
+
storeCandidate(input, runPath);
|
|
34
|
+
const workspace = join(runPath, "tasks", `${task.id}-${attempt}-g${journal.state.generation}`);
|
|
35
|
+
materializeCandidate(input, workspace);
|
|
36
|
+
journal.append({
|
|
37
|
+
kind: "task_started",
|
|
38
|
+
taskId: task.id,
|
|
39
|
+
attempt,
|
|
40
|
+
inputDigest: input.digest,
|
|
41
|
+
observedMs: observeWork(context),
|
|
42
|
+
});
|
|
43
|
+
const { result } = await executeRunCommand(journal, { role: "writer", argv, workspace, deadline, claimId: null }, { ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) });
|
|
44
|
+
if (result.failure === "deadline" || result.failure === "cancelled")
|
|
45
|
+
throw new VerifiedRunError(result.failure);
|
|
46
|
+
let outputDigest = null;
|
|
47
|
+
let failure = result.failure;
|
|
48
|
+
if (!failure) {
|
|
49
|
+
try {
|
|
50
|
+
const output = captureCandidate(workspace, contract.budget);
|
|
51
|
+
assertCandidateScope(input.manifest, output.manifest, task.writablePaths);
|
|
52
|
+
storeCandidate(output, runPath);
|
|
53
|
+
outputDigest = output.digest;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (!(error instanceof VerifiedRunError) ||
|
|
57
|
+
!["scope_changed", "file_type", "storage_limit"].includes(error.code))
|
|
58
|
+
throw error;
|
|
59
|
+
failure = error.code;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
journal.append({
|
|
63
|
+
kind: "task_finished",
|
|
64
|
+
taskId: task.id,
|
|
65
|
+
attempt,
|
|
66
|
+
outputDigest,
|
|
67
|
+
failure,
|
|
68
|
+
observedMs: observeWork(context),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Deliberately one child at a time: all ownership and process fencing still use the existing broker. */
|
|
72
|
+
export async function executeDag(context, options) {
|
|
73
|
+
const { contract, journal, runPath } = context;
|
|
74
|
+
if (contract.profile !== "linux-command-dag-v1")
|
|
75
|
+
throw new VerifiedRunError("unsupported");
|
|
76
|
+
ensureDurableDirectorySync(join(runPath, "tasks"));
|
|
77
|
+
const order = orderRunDag(contract.writer.tasks);
|
|
78
|
+
for (;;) {
|
|
79
|
+
const ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));
|
|
80
|
+
const next = order.find((task) => ready.has(task.id));
|
|
81
|
+
if (!next)
|
|
82
|
+
break;
|
|
83
|
+
await executeTask(context, next, options.deadline);
|
|
84
|
+
}
|
|
85
|
+
if (journal.state.tasks.some((task) => task.status !== "succeeded" || task.generation !== journal.state.generation)) {
|
|
86
|
+
journal.append({ kind: "tasks_paused" });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
observeWork(context);
|
|
90
|
+
materializeCandidate(composeDagCandidate(context, order), options.workspace);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=dag-phase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-phase.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-phase.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { orderRunDag, type RunDagTask, runDagAncestors } from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport { executeRunCommand } from \"./owned-execution.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction observeWork(context: RunPhaseContext): number {\n\tconst budget = context.journal.state.budget;\n\tif (!budget) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst clock = readRunClock();\n\tif (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0) throw new VerifiedRunError(\"deadline\");\n\treturn clock.nowMs;\n}\n\nasync function executeTask(context: RunPhaseContext, task: RunDagTask, deadline: number): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tif (context.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst previous = journal.state.tasks.find((item) => item.taskId === task.id);\n\tif (previous?.status !== \"pending\") throw new VerifiedRunError(\"task_not_ready\");\n\tconst attempt = previous.attempt + 1;\n\tconst argv = task.attempts[previous.attempt];\n\tif (!argv) throw new VerifiedRunError(\"task_attempt_limit\");\n\tconst input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));\n\tstoreCandidate(input, runPath);\n\tconst workspace = join(runPath, \"tasks\", `${task.id}-${attempt}-g${journal.state.generation}`);\n\tmaterializeCandidate(input, workspace);\n\tjournal.append({\n\t\tkind: \"task_started\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\tinputDigest: input.digest,\n\t\tobservedMs: observeWork(context),\n\t});\n\tconst { result } = await executeRunCommand(\n\t\tjournal,\n\t\t{ role: \"writer\", argv, workspace, deadline, claimId: null },\n\t\t{ ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) },\n\t);\n\tif (result.failure === \"deadline\" || result.failure === \"cancelled\") throw new VerifiedRunError(result.failure);\n\tlet outputDigest: string | null = null;\n\tlet failure = result.failure;\n\tif (!failure) {\n\t\ttry {\n\t\t\tconst output = captureCandidate(workspace, contract.budget);\n\t\t\tassertCandidateScope(input.manifest, output.manifest, task.writablePaths);\n\t\t\tstoreCandidate(output, runPath);\n\t\t\toutputDigest = output.digest;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\t!(error instanceof VerifiedRunError) ||\n\t\t\t\t![\"scope_changed\", \"file_type\", \"storage_limit\"].includes(error.code)\n\t\t\t)\n\t\t\t\tthrow error;\n\t\t\tfailure = error.code;\n\t\t}\n\t}\n\tjournal.append({\n\t\tkind: \"task_finished\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\toutputDigest,\n\t\tfailure,\n\t\tobservedMs: observeWork(context),\n\t});\n}\n\n/** Deliberately one child at a time: all ownership and process fencing still use the existing broker. */\nexport async function executeDag(\n\tcontext: RunPhaseContext,\n\toptions: { readonly workspace: string; readonly deadline: number },\n): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tensureDurableDirectorySync(join(runPath, \"tasks\"));\n\tconst order = orderRunDag(contract.writer.tasks);\n\tfor (;;) {\n\t\tconst ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));\n\t\tconst next = order.find((task) => ready.has(task.id));\n\t\tif (!next) break;\n\t\tawait executeTask(context, next, options.deadline);\n\t}\n\tif (\n\t\tjournal.state.tasks.some((task) => task.status !== \"succeeded\" || task.generation !== journal.state.generation)\n\t) {\n\t\tjournal.append({ kind: \"tasks_paused\" });\n\t\treturn;\n\t}\n\tobserveWork(context);\n\tmaterializeCandidate(composeDagCandidate(context, order), options.workspace);\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RunDagTask, RunDagWriter } from "omk-protocol";
|
|
2
|
+
import type { DagEvent } from "./dag-types.ts";
|
|
3
|
+
import type { RunProjection, WriterReduction } from "./run-types.ts";
|
|
4
|
+
export declare function readyDagTasks(writer: RunDagWriter, state: RunProjection): readonly RunDagTask[];
|
|
5
|
+
/** Task outputs are execution checkpoints, never verifier receipts or completion authority. */
|
|
6
|
+
export declare function reduceDagEvent(context: WriterReduction, event: DagEvent): void;
|
|
7
|
+
//# sourceMappingURL=dag-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-projection.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,UAAU,EAAE,CAU/F;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAsF9E","sourcesContent":["import type { RunDagTask, RunDagWriter } from \"omk-protocol\";\nimport type { DagEvent, RunTaskProjection } from \"./dag-types.ts\";\nimport type { RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport function readyDagTasks(writer: RunDagWriter, state: RunProjection): readonly RunDagTask[] {\n\tconst states = new Map(state.tasks.map((task) => [task.taskId, task]));\n\treturn writer.tasks.filter(\n\t\t(task) =>\n\t\t\tstates.get(task.id)?.status === \"pending\" &&\n\t\t\ttask.dependsOn.every((id) => {\n\t\t\t\tconst dependency = states.get(id);\n\t\t\t\treturn dependency?.status === \"succeeded\" && dependency.generation === state.generation;\n\t\t\t}),\n\t);\n}\n\n/** Task outputs are execution checkpoints, never verifier receipts or completion authority. */\nexport function reduceDagEvent(context: WriterReduction, event: DagEvent): void {\n\tconst { state, contract } = context;\n\tif (\n\t\tcontract.profile !== \"linux-command-dag-v1\" ||\n\t\t!state.inputDigest ||\n\t\t!state.budget ||\n\t\tstate.candidateDigest ||\n\t\tstate.writerOpen ||\n\t\tstate.activeExecutionIds.length ||\n\t\tstate.execution === \"paused\"\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (event.kind === \"tasks_paused\") {\n\t\tif (\n\t\t\tstate.tasks.some((task) => task.status === \"running\") ||\n\t\t\t!state.tasks.some((task) => task.status === \"failed\") ||\n\t\t\treadyDagTasks(contract.writer, state).length\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\tcontext.state = { ...state, execution: \"paused\", settlement: \"settled\" };\n\t\treturn;\n\t}\n\tif (\n\t\tevent.observedMs < (state.lastClockMs ?? state.budget.startedMs) ||\n\t\tevent.observedMs >= state.budget.workDeadlineMs\n\t)\n\t\tthrow new VerifiedRunError(\"deadline\");\n\tconst task = state.tasks.find((task) => task.taskId === event.taskId);\n\tconst definition = contract.writer.tasks.find((task) => task.id === event.taskId);\n\tif (!task || !definition) throw new VerifiedRunError(\"integrity\");\n\tlet next: RunTaskProjection;\n\tswitch (event.kind) {\n\t\tcase \"task_started\":\n\t\t\tif (\n\t\t\t\ttask.status !== \"pending\" ||\n\t\t\t\tstate.tasks.some((task) => task.status === \"running\") ||\n\t\t\t\tevent.attempt !== task.attempt + 1 ||\n\t\t\t\tevent.attempt > definition.attempts.length ||\n\t\t\t\t!readyDagTasks(contract.writer, state).some((task) => task.id === event.taskId)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"task_not_ready\");\n\t\t\tnext = {\n\t\t\t\ttaskId: task.taskId,\n\t\t\t\tgeneration: state.generation,\n\t\t\t\tattempt: event.attempt,\n\t\t\t\tstatus: \"running\",\n\t\t\t\tinputDigest: event.inputDigest,\n\t\t\t\toutputDigest: null,\n\t\t\t\tfailure: null,\n\t\t\t};\n\t\t\tcontext.writerStarted = false;\n\t\t\tcontext.writerFinished = false;\n\t\t\tbreak;\n\t\tcase \"task_finished\":\n\t\t\tif (\n\t\t\t\ttask.status !== \"running\" ||\n\t\t\t\ttask.generation !== state.generation ||\n\t\t\t\ttask.attempt !== event.attempt ||\n\t\t\t\t!context.writerStarted\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\tif (event.outputDigest !== null) {\n\t\t\t\tif (event.failure !== null || state.failure || !context.writerFinished)\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...task, status: \"succeeded\", outputDigest: event.outputDigest };\n\t\t\t} else {\n\t\t\t\tif (!event.failure || (state.failure && event.failure !== state.failure))\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...task, status: \"failed\", failure: event.failure };\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault: {\n\t\t\tconst exhaustive: never = event;\n\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t}\n\t}\n\tconst tasks = state.tasks.map((task) => (task.taskId === next.taskId ? next : task));\n\tcontext.writerFinished = tasks.every((task) => task.status === \"succeeded\" && task.generation === state.generation);\n\tcontext.state = {\n\t\t...state,\n\t\ttasks,\n\t\texecution: \"running\",\n\t\tsettlement: \"settled\",\n\t\tfailure: null,\n\t\tlastClockMs: event.observedMs,\n\t};\n}\n"]}
|