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,90 @@
|
|
|
1
|
+
import { VerifiedRunError } from "./storage.js";
|
|
2
|
+
export function readyDagTasks(writer, state) {
|
|
3
|
+
const states = new Map(state.tasks.map((task) => [task.taskId, task]));
|
|
4
|
+
return writer.tasks.filter((task) => states.get(task.id)?.status === "pending" &&
|
|
5
|
+
task.dependsOn.every((id) => {
|
|
6
|
+
const dependency = states.get(id);
|
|
7
|
+
return dependency?.status === "succeeded" && dependency.generation === state.generation;
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
/** Task outputs are execution checkpoints, never verifier receipts or completion authority. */
|
|
11
|
+
export function reduceDagEvent(context, event) {
|
|
12
|
+
const { state, contract } = context;
|
|
13
|
+
if (contract.profile !== "linux-command-dag-v1" ||
|
|
14
|
+
!state.inputDigest ||
|
|
15
|
+
!state.budget ||
|
|
16
|
+
state.candidateDigest ||
|
|
17
|
+
state.writerOpen ||
|
|
18
|
+
state.activeExecutionIds.length ||
|
|
19
|
+
state.execution === "paused")
|
|
20
|
+
throw new VerifiedRunError("integrity");
|
|
21
|
+
if (event.kind === "tasks_paused") {
|
|
22
|
+
if (state.tasks.some((task) => task.status === "running") ||
|
|
23
|
+
!state.tasks.some((task) => task.status === "failed") ||
|
|
24
|
+
readyDagTasks(contract.writer, state).length)
|
|
25
|
+
throw new VerifiedRunError("integrity");
|
|
26
|
+
context.state = { ...state, execution: "paused", settlement: "settled" };
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (event.observedMs < (state.lastClockMs ?? state.budget.startedMs) ||
|
|
30
|
+
event.observedMs >= state.budget.workDeadlineMs)
|
|
31
|
+
throw new VerifiedRunError("deadline");
|
|
32
|
+
const task = state.tasks.find((task) => task.taskId === event.taskId);
|
|
33
|
+
const definition = contract.writer.tasks.find((task) => task.id === event.taskId);
|
|
34
|
+
if (!task || !definition)
|
|
35
|
+
throw new VerifiedRunError("integrity");
|
|
36
|
+
let next;
|
|
37
|
+
switch (event.kind) {
|
|
38
|
+
case "task_started":
|
|
39
|
+
if (task.status !== "pending" ||
|
|
40
|
+
state.tasks.some((task) => task.status === "running") ||
|
|
41
|
+
event.attempt !== task.attempt + 1 ||
|
|
42
|
+
event.attempt > definition.attempts.length ||
|
|
43
|
+
!readyDagTasks(contract.writer, state).some((task) => task.id === event.taskId))
|
|
44
|
+
throw new VerifiedRunError("task_not_ready");
|
|
45
|
+
next = {
|
|
46
|
+
taskId: task.taskId,
|
|
47
|
+
generation: state.generation,
|
|
48
|
+
attempt: event.attempt,
|
|
49
|
+
status: "running",
|
|
50
|
+
inputDigest: event.inputDigest,
|
|
51
|
+
outputDigest: null,
|
|
52
|
+
failure: null,
|
|
53
|
+
};
|
|
54
|
+
context.writerStarted = false;
|
|
55
|
+
context.writerFinished = false;
|
|
56
|
+
break;
|
|
57
|
+
case "task_finished":
|
|
58
|
+
if (task.status !== "running" ||
|
|
59
|
+
task.generation !== state.generation ||
|
|
60
|
+
task.attempt !== event.attempt ||
|
|
61
|
+
!context.writerStarted)
|
|
62
|
+
throw new VerifiedRunError("integrity");
|
|
63
|
+
if (event.outputDigest !== null) {
|
|
64
|
+
if (event.failure !== null || state.failure || !context.writerFinished)
|
|
65
|
+
throw new VerifiedRunError("integrity");
|
|
66
|
+
next = { ...task, status: "succeeded", outputDigest: event.outputDigest };
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (!event.failure || (state.failure && event.failure !== state.failure))
|
|
70
|
+
throw new VerifiedRunError("integrity");
|
|
71
|
+
next = { ...task, status: "failed", failure: event.failure };
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
default: {
|
|
75
|
+
const exhaustive = event;
|
|
76
|
+
throw new VerifiedRunError(String(exhaustive));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const tasks = state.tasks.map((task) => (task.taskId === next.taskId ? next : task));
|
|
80
|
+
context.writerFinished = tasks.every((task) => task.status === "succeeded" && task.generation === state.generation);
|
|
81
|
+
context.state = {
|
|
82
|
+
...state,
|
|
83
|
+
tasks,
|
|
84
|
+
execution: "running",
|
|
85
|
+
settlement: "settled",
|
|
86
|
+
failure: null,
|
|
87
|
+
lastClockMs: event.observedMs,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=dag-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-projection.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-projection.ts"],"names":[],"mappings":"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","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"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RunTaskRetryCommand } from "omk-protocol";
|
|
2
|
+
import type { RunProjection } from "./run-types.ts";
|
|
3
|
+
export interface TaskRecoveryInspection {
|
|
4
|
+
readonly state: RunProjection;
|
|
5
|
+
readonly readiness: "ready" | "blocked";
|
|
6
|
+
readonly reason: string | null;
|
|
7
|
+
readonly retryableTaskIds: readonly string[];
|
|
8
|
+
readonly remainingWorkMs: number | null;
|
|
9
|
+
readonly ownership: "lease_required";
|
|
10
|
+
}
|
|
11
|
+
export declare function inspectTaskRecovery(runPath: string): TaskRecoveryInspection;
|
|
12
|
+
export declare function retryDagTasks(runPath: string, command: RunTaskRetryCommand, signal?: AbortSignal): Promise<RunProjection>;
|
|
13
|
+
//# sourceMappingURL=dag-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-recovery.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-recovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAmB,MAAM,cAAc,CAAC;AAUzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMpD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACrC;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CA+B3E;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CA0BxB","sourcesContent":["import { join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport { type RunTaskRetryCommand, runDagAncestors } from \"omk-protocol\";\nimport { probeVerifiedSandbox } from \"./broker.ts\";\nimport { assertCandidateScope, loadCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { executeDag } from \"./dag-phase.ts\";\nimport { assertTaskSelection, taskCheckpoints } from \"./dag-retry-projection.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { requireRunJournal, withRecoveryLease } from \"./recovery-command.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { assertWorkRecoverable } from \"./work-recovery.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\n\nexport interface TaskRecoveryInspection {\n\treadonly state: RunProjection;\n\treadonly readiness: \"ready\" | \"blocked\";\n\treadonly reason: string | null;\n\treadonly retryableTaskIds: readonly string[];\n\treadonly remainingWorkMs: number | null;\n\treadonly ownership: \"lease_required\";\n}\n\nfunction assertDagRecoverable(runPath: string, snapshot: JournalSnapshot) {\n\tconst recovery = assertWorkRecoverable(runPath, snapshot);\n\tconst { contract } = recovery;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"task_recovery_unavailable\");\n\tfor (const task of snapshot.state.tasks) {\n\t\tif (task.status === \"pending\") continue;\n\t\tconst definition = contract.writer.tasks.find((item) => item.id === task.taskId);\n\t\tif (!definition) throw new VerifiedRunError(\"integrity\");\n\t\tconst expected = composeDagCandidate(\n\t\t\t{ runPath, contract, journal: snapshot },\n\t\t\trunDagAncestors(contract.writer.tasks, task.taskId),\n\t\t);\n\t\tconst input = loadCandidate(runPath, task.inputDigest, contract.budget);\n\t\tif (input.digest !== expected.digest) throw new VerifiedRunError(\"task_checkpoint_mismatch\");\n\t\tif (task.status === \"succeeded\")\n\t\t\tassertCandidateScope(\n\t\t\t\tinput.manifest,\n\t\t\t\tloadCandidate(runPath, task.outputDigest, contract.budget).manifest,\n\t\t\t\tdefinition.writablePaths,\n\t\t\t);\n\t}\n\treturn { contract, remainingMs: recovery.remainingMs };\n}\n\nexport function inspectTaskRecovery(runPath: string): TaskRecoveryInspection {\n\tconst snapshot = requireRunJournal(runPath);\n\ttry {\n\t\tconst { contract, remainingMs } = assertDagRecoverable(runPath, snapshot);\n\t\tconst taskIds = snapshot.state.tasks\n\t\t\t.filter(\n\t\t\t\t(task) =>\n\t\t\t\t\t(task.status === \"failed\" || task.status === \"running\") &&\n\t\t\t\t\ttask.attempt < (contract.writer.tasks.find((item) => item.id === task.taskId)?.attempts.length ?? 0),\n\t\t\t)\n\t\t\t.map((task) => task.taskId);\n\t\tassertTaskSelection(contract, snapshot.state, taskIds);\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"ready\",\n\t\t\treason: null,\n\t\t\tretryableTaskIds: Object.freeze(taskIds),\n\t\t\tremainingWorkMs: remainingMs,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) throw error;\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"blocked\",\n\t\t\treason: error instanceof VerifiedRunError ? error.code : \"integrity\",\n\t\t\tretryableTaskIds: Object.freeze([]),\n\t\t\tremainingWorkMs: null,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t}\n}\n\nexport async function retryDagTasks(\n\trunPath: string,\n\tcommand: RunTaskRetryCommand,\n\tsignal?: AbortSignal,\n): Promise<RunProjection> {\n\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\treturn withRecoveryLease(runPath, command, async ({ snapshot, journal }) => {\n\t\tconst { contract } = assertDagRecoverable(runPath, snapshot);\n\t\tassertTaskSelection(contract, snapshot.state, command.taskIds);\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tassertDagRecoverable(runPath, snapshot);\n\t\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tjournal.append({\n\t\t\tkind: \"tasks_retried\",\n\t\t\tcommand,\n\t\t\tobservedMs: readRunClock().nowMs,\n\t\t\treconciledExecutionIds: snapshot.state.activeExecutionIds,\n\t\t\tadopted: taskCheckpoints(snapshot.state),\n\t\t});\n\t\tconst budget = journal.state.budget;\n\t\tif (!budget) throw new VerifiedRunError(\"integrity\");\n\t\tconst deadline = performance.now() + remainingRunTime(budget, budget.workDeadlineMs);\n\t\tconst workspace = join(runPath, `writer-${journal.state.generation}`);\n\t\tconst context = { runPath, contract, journal, ...(signal ? { signal } : {}) };\n\t\tawait executeDag(context, { workspace, deadline });\n\t\tif (journal.state.execution === \"paused\") return journal.state;\n\t\tpublishWriterCandidate(context, workspace, deadline);\n\t\treturn verifyCandidate(context);\n\t});\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { runDagAncestors } from "omk-protocol";
|
|
4
|
+
import { probeVerifiedSandbox } from "./broker.js";
|
|
5
|
+
import { assertCandidateScope, loadCandidate } from "./candidate.js";
|
|
6
|
+
import { preflightCheckReceipts } from "./check-receipt.js";
|
|
7
|
+
import { composeDagCandidate } from "./dag-candidates.js";
|
|
8
|
+
import { executeDag } from "./dag-phase.js";
|
|
9
|
+
import { assertTaskSelection, taskCheckpoints } from "./dag-retry-projection.js";
|
|
10
|
+
import { readRunClock, remainingRunTime } from "./recovery-clock.js";
|
|
11
|
+
import { requireRunJournal, withRecoveryLease } from "./recovery-command.js";
|
|
12
|
+
import { VerifiedRunError } from "./storage.js";
|
|
13
|
+
import { verifyCandidate } from "./verification-phase.js";
|
|
14
|
+
import { assertWorkRecoverable } from "./work-recovery.js";
|
|
15
|
+
import { publishWriterCandidate } from "./writer-completion.js";
|
|
16
|
+
function assertDagRecoverable(runPath, snapshot) {
|
|
17
|
+
const recovery = assertWorkRecoverable(runPath, snapshot);
|
|
18
|
+
const { contract } = recovery;
|
|
19
|
+
if (contract.profile !== "linux-command-dag-v1")
|
|
20
|
+
throw new VerifiedRunError("task_recovery_unavailable");
|
|
21
|
+
for (const task of snapshot.state.tasks) {
|
|
22
|
+
if (task.status === "pending")
|
|
23
|
+
continue;
|
|
24
|
+
const definition = contract.writer.tasks.find((item) => item.id === task.taskId);
|
|
25
|
+
if (!definition)
|
|
26
|
+
throw new VerifiedRunError("integrity");
|
|
27
|
+
const expected = composeDagCandidate({ runPath, contract, journal: snapshot }, runDagAncestors(contract.writer.tasks, task.taskId));
|
|
28
|
+
const input = loadCandidate(runPath, task.inputDigest, contract.budget);
|
|
29
|
+
if (input.digest !== expected.digest)
|
|
30
|
+
throw new VerifiedRunError("task_checkpoint_mismatch");
|
|
31
|
+
if (task.status === "succeeded")
|
|
32
|
+
assertCandidateScope(input.manifest, loadCandidate(runPath, task.outputDigest, contract.budget).manifest, definition.writablePaths);
|
|
33
|
+
}
|
|
34
|
+
return { contract, remainingMs: recovery.remainingMs };
|
|
35
|
+
}
|
|
36
|
+
export function inspectTaskRecovery(runPath) {
|
|
37
|
+
const snapshot = requireRunJournal(runPath);
|
|
38
|
+
try {
|
|
39
|
+
const { contract, remainingMs } = assertDagRecoverable(runPath, snapshot);
|
|
40
|
+
const taskIds = snapshot.state.tasks
|
|
41
|
+
.filter((task) => (task.status === "failed" || task.status === "running") &&
|
|
42
|
+
task.attempt < (contract.writer.tasks.find((item) => item.id === task.taskId)?.attempts.length ?? 0))
|
|
43
|
+
.map((task) => task.taskId);
|
|
44
|
+
assertTaskSelection(contract, snapshot.state, taskIds);
|
|
45
|
+
return Object.freeze({
|
|
46
|
+
state: snapshot.state,
|
|
47
|
+
readiness: "ready",
|
|
48
|
+
reason: null,
|
|
49
|
+
retryableTaskIds: Object.freeze(taskIds),
|
|
50
|
+
remainingWorkMs: remainingMs,
|
|
51
|
+
ownership: "lease_required",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (!(error instanceof Error))
|
|
56
|
+
throw error;
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
state: snapshot.state,
|
|
59
|
+
readiness: "blocked",
|
|
60
|
+
reason: error instanceof VerifiedRunError ? error.code : "integrity",
|
|
61
|
+
retryableTaskIds: Object.freeze([]),
|
|
62
|
+
remainingWorkMs: null,
|
|
63
|
+
ownership: "lease_required",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function retryDagTasks(runPath, command, signal) {
|
|
68
|
+
if (signal?.aborted)
|
|
69
|
+
throw new VerifiedRunError("cancelled");
|
|
70
|
+
return withRecoveryLease(runPath, command, async ({ snapshot, journal }) => {
|
|
71
|
+
const { contract } = assertDagRecoverable(runPath, snapshot);
|
|
72
|
+
assertTaskSelection(contract, snapshot.state, command.taskIds);
|
|
73
|
+
preflightCheckReceipts(contract);
|
|
74
|
+
probeVerifiedSandbox();
|
|
75
|
+
assertDagRecoverable(runPath, snapshot);
|
|
76
|
+
if (signal?.aborted)
|
|
77
|
+
throw new VerifiedRunError("cancelled");
|
|
78
|
+
journal.append({
|
|
79
|
+
kind: "tasks_retried",
|
|
80
|
+
command,
|
|
81
|
+
observedMs: readRunClock().nowMs,
|
|
82
|
+
reconciledExecutionIds: snapshot.state.activeExecutionIds,
|
|
83
|
+
adopted: taskCheckpoints(snapshot.state),
|
|
84
|
+
});
|
|
85
|
+
const budget = journal.state.budget;
|
|
86
|
+
if (!budget)
|
|
87
|
+
throw new VerifiedRunError("integrity");
|
|
88
|
+
const deadline = performance.now() + remainingRunTime(budget, budget.workDeadlineMs);
|
|
89
|
+
const workspace = join(runPath, `writer-${journal.state.generation}`);
|
|
90
|
+
const context = { runPath, contract, journal, ...(signal ? { signal } : {}) };
|
|
91
|
+
await executeDag(context, { workspace, deadline });
|
|
92
|
+
if (journal.state.execution === "paused")
|
|
93
|
+
return journal.state;
|
|
94
|
+
publishWriterCandidate(context, workspace, deadline);
|
|
95
|
+
return verifyCandidate(context);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=dag-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-recovery.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-recovery.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport { type RunTaskRetryCommand, runDagAncestors } from \"omk-protocol\";\nimport { probeVerifiedSandbox } from \"./broker.ts\";\nimport { assertCandidateScope, loadCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { executeDag } from \"./dag-phase.ts\";\nimport { assertTaskSelection, taskCheckpoints } from \"./dag-retry-projection.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { requireRunJournal, withRecoveryLease } from \"./recovery-command.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { assertWorkRecoverable } from \"./work-recovery.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\n\nexport interface TaskRecoveryInspection {\n\treadonly state: RunProjection;\n\treadonly readiness: \"ready\" | \"blocked\";\n\treadonly reason: string | null;\n\treadonly retryableTaskIds: readonly string[];\n\treadonly remainingWorkMs: number | null;\n\treadonly ownership: \"lease_required\";\n}\n\nfunction assertDagRecoverable(runPath: string, snapshot: JournalSnapshot) {\n\tconst recovery = assertWorkRecoverable(runPath, snapshot);\n\tconst { contract } = recovery;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"task_recovery_unavailable\");\n\tfor (const task of snapshot.state.tasks) {\n\t\tif (task.status === \"pending\") continue;\n\t\tconst definition = contract.writer.tasks.find((item) => item.id === task.taskId);\n\t\tif (!definition) throw new VerifiedRunError(\"integrity\");\n\t\tconst expected = composeDagCandidate(\n\t\t\t{ runPath, contract, journal: snapshot },\n\t\t\trunDagAncestors(contract.writer.tasks, task.taskId),\n\t\t);\n\t\tconst input = loadCandidate(runPath, task.inputDigest, contract.budget);\n\t\tif (input.digest !== expected.digest) throw new VerifiedRunError(\"task_checkpoint_mismatch\");\n\t\tif (task.status === \"succeeded\")\n\t\t\tassertCandidateScope(\n\t\t\t\tinput.manifest,\n\t\t\t\tloadCandidate(runPath, task.outputDigest, contract.budget).manifest,\n\t\t\t\tdefinition.writablePaths,\n\t\t\t);\n\t}\n\treturn { contract, remainingMs: recovery.remainingMs };\n}\n\nexport function inspectTaskRecovery(runPath: string): TaskRecoveryInspection {\n\tconst snapshot = requireRunJournal(runPath);\n\ttry {\n\t\tconst { contract, remainingMs } = assertDagRecoverable(runPath, snapshot);\n\t\tconst taskIds = snapshot.state.tasks\n\t\t\t.filter(\n\t\t\t\t(task) =>\n\t\t\t\t\t(task.status === \"failed\" || task.status === \"running\") &&\n\t\t\t\t\ttask.attempt < (contract.writer.tasks.find((item) => item.id === task.taskId)?.attempts.length ?? 0),\n\t\t\t)\n\t\t\t.map((task) => task.taskId);\n\t\tassertTaskSelection(contract, snapshot.state, taskIds);\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"ready\",\n\t\t\treason: null,\n\t\t\tretryableTaskIds: Object.freeze(taskIds),\n\t\t\tremainingWorkMs: remainingMs,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) throw error;\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"blocked\",\n\t\t\treason: error instanceof VerifiedRunError ? error.code : \"integrity\",\n\t\t\tretryableTaskIds: Object.freeze([]),\n\t\t\tremainingWorkMs: null,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t}\n}\n\nexport async function retryDagTasks(\n\trunPath: string,\n\tcommand: RunTaskRetryCommand,\n\tsignal?: AbortSignal,\n): Promise<RunProjection> {\n\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\treturn withRecoveryLease(runPath, command, async ({ snapshot, journal }) => {\n\t\tconst { contract } = assertDagRecoverable(runPath, snapshot);\n\t\tassertTaskSelection(contract, snapshot.state, command.taskIds);\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tassertDagRecoverable(runPath, snapshot);\n\t\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tjournal.append({\n\t\t\tkind: \"tasks_retried\",\n\t\t\tcommand,\n\t\t\tobservedMs: readRunClock().nowMs,\n\t\t\treconciledExecutionIds: snapshot.state.activeExecutionIds,\n\t\t\tadopted: taskCheckpoints(snapshot.state),\n\t\t});\n\t\tconst budget = journal.state.budget;\n\t\tif (!budget) throw new VerifiedRunError(\"integrity\");\n\t\tconst deadline = performance.now() + remainingRunTime(budget, budget.workDeadlineMs);\n\t\tconst workspace = join(runPath, `writer-${journal.state.generation}`);\n\t\tconst context = { runPath, contract, journal, ...(signal ? { signal } : {}) };\n\t\tawait executeDag(context, { workspace, deadline });\n\t\tif (journal.state.execution === \"paused\") return journal.state;\n\t\tpublishWriterCandidate(context, workspace, deadline);\n\t\treturn verifyCandidate(context);\n\t});\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RunContract } from "omk-protocol";
|
|
2
|
+
import type { RunTaskCheckpoint, RunTaskProjection } from "./dag-types.ts";
|
|
3
|
+
import type { RunEvent, RunProjection, WriterReduction } from "./run-types.ts";
|
|
4
|
+
export declare function taskCheckpoints(state: RunProjection): readonly RunTaskCheckpoint[];
|
|
5
|
+
export declare function assertTaskSelection(contract: RunContract, state: RunProjection, taskIds: readonly string[]): void;
|
|
6
|
+
export declare function retryTaskProjection(context: WriterReduction, event: Extract<RunEvent, {
|
|
7
|
+
kind: "tasks_retried";
|
|
8
|
+
}>): readonly RunTaskProjection[];
|
|
9
|
+
//# sourceMappingURL=dag-retry-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-retry-projection.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-retry-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAG/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,iBAAiB,EAAE,CAElF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAuBjH;AAED,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,GACjD,SAAS,iBAAiB,EAAE,CAuB9B","sourcesContent":["import type { RunContract } from \"omk-protocol\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport type { RunTaskCheckpoint, RunTaskProjection } from \"./dag-types.ts\";\nimport type { RunEvent, RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\nexport function taskCheckpoints(state: RunProjection): readonly RunTaskCheckpoint[] {\n\treturn state.tasks.filter((task): task is RunTaskCheckpoint => task.status === \"succeeded\");\n}\n\nexport function assertTaskSelection(contract: RunContract, state: RunProjection, taskIds: readonly string[]): void {\n\tif (contract.profile !== \"linux-command-dag-v1\" || !state.inputDigest || state.candidateDigest || state.writerOpen)\n\t\tthrow new VerifiedRunError(\"task_recovery_unavailable\");\n\tfor (const id of taskIds) {\n\t\tconst task = state.tasks.find((task) => task.taskId === id);\n\t\tconst definition = contract.writer.tasks.find((task) => task.id === id);\n\t\tif (!task || !definition || (task.status !== \"failed\" && task.status !== \"running\"))\n\t\t\tthrow new VerifiedRunError(\"task_not_retryable\");\n\t\tif (task.attempt >= definition.attempts.length) throw new VerifiedRunError(\"task_attempt_limit\");\n\t}\n\tif (\n\t\tstate.tasks.some(\n\t\t\t(task) =>\n\t\t\t\ttask.generation !== state.generation || (task.status === \"running\" && !taskIds.includes(task.taskId)),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"task_selection\");\n\tif (\n\t\t!taskIds.length &&\n\t\t!readyDagTasks(contract.writer, state).length &&\n\t\t!state.tasks.every((task) => task.status === \"succeeded\")\n\t)\n\t\tthrow new VerifiedRunError(\"task_selection\");\n}\n\nexport function retryTaskProjection(\n\tcontext: WriterReduction,\n\tevent: Extract<RunEvent, { kind: \"tasks_retried\" }>,\n): readonly RunTaskProjection[] {\n\tconst { state, contract } = context;\n\tassertTaskSelection(contract, state, event.command.taskIds);\n\tif (\n\t\tevent.command.baseDigest !== state.inputDigest ||\n\t\tstate.inputDigest !== contract.workspace.baseDigest ||\n\t\tdigestObject(event.adopted) !== digestObject(taskCheckpoints(state))\n\t)\n\t\tthrow new VerifiedRunError(\"task_checkpoint_mismatch\");\n\treturn state.tasks.map(\n\t\t(task): RunTaskProjection =>\n\t\t\tevent.command.taskIds.includes(task.taskId)\n\t\t\t\t? {\n\t\t\t\t\t\ttaskId: task.taskId,\n\t\t\t\t\t\tattempt: task.attempt,\n\t\t\t\t\t\tgeneration: state.generation + 1,\n\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\tinputDigest: null,\n\t\t\t\t\t\toutputDigest: null,\n\t\t\t\t\t\tfailure: null,\n\t\t\t\t\t}\n\t\t\t\t: { ...task, generation: state.generation + 1 },\n\t);\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readyDagTasks } from "./dag-projection.js";
|
|
2
|
+
import { digestObject, VerifiedRunError } from "./storage.js";
|
|
3
|
+
export function taskCheckpoints(state) {
|
|
4
|
+
return state.tasks.filter((task) => task.status === "succeeded");
|
|
5
|
+
}
|
|
6
|
+
export function assertTaskSelection(contract, state, taskIds) {
|
|
7
|
+
if (contract.profile !== "linux-command-dag-v1" || !state.inputDigest || state.candidateDigest || state.writerOpen)
|
|
8
|
+
throw new VerifiedRunError("task_recovery_unavailable");
|
|
9
|
+
for (const id of taskIds) {
|
|
10
|
+
const task = state.tasks.find((task) => task.taskId === id);
|
|
11
|
+
const definition = contract.writer.tasks.find((task) => task.id === id);
|
|
12
|
+
if (!task || !definition || (task.status !== "failed" && task.status !== "running"))
|
|
13
|
+
throw new VerifiedRunError("task_not_retryable");
|
|
14
|
+
if (task.attempt >= definition.attempts.length)
|
|
15
|
+
throw new VerifiedRunError("task_attempt_limit");
|
|
16
|
+
}
|
|
17
|
+
if (state.tasks.some((task) => task.generation !== state.generation || (task.status === "running" && !taskIds.includes(task.taskId))))
|
|
18
|
+
throw new VerifiedRunError("task_selection");
|
|
19
|
+
if (!taskIds.length &&
|
|
20
|
+
!readyDagTasks(contract.writer, state).length &&
|
|
21
|
+
!state.tasks.every((task) => task.status === "succeeded"))
|
|
22
|
+
throw new VerifiedRunError("task_selection");
|
|
23
|
+
}
|
|
24
|
+
export function retryTaskProjection(context, event) {
|
|
25
|
+
const { state, contract } = context;
|
|
26
|
+
assertTaskSelection(contract, state, event.command.taskIds);
|
|
27
|
+
if (event.command.baseDigest !== state.inputDigest ||
|
|
28
|
+
state.inputDigest !== contract.workspace.baseDigest ||
|
|
29
|
+
digestObject(event.adopted) !== digestObject(taskCheckpoints(state)))
|
|
30
|
+
throw new VerifiedRunError("task_checkpoint_mismatch");
|
|
31
|
+
return state.tasks.map((task) => event.command.taskIds.includes(task.taskId)
|
|
32
|
+
? {
|
|
33
|
+
taskId: task.taskId,
|
|
34
|
+
attempt: task.attempt,
|
|
35
|
+
generation: state.generation + 1,
|
|
36
|
+
status: "pending",
|
|
37
|
+
inputDigest: null,
|
|
38
|
+
outputDigest: null,
|
|
39
|
+
failure: null,
|
|
40
|
+
}
|
|
41
|
+
: { ...task, generation: state.generation + 1 });
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=dag-retry-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-retry-projection.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-retry-projection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RunContract } from \"omk-protocol\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport type { RunTaskCheckpoint, RunTaskProjection } from \"./dag-types.ts\";\nimport type { RunEvent, RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\nexport function taskCheckpoints(state: RunProjection): readonly RunTaskCheckpoint[] {\n\treturn state.tasks.filter((task): task is RunTaskCheckpoint => task.status === \"succeeded\");\n}\n\nexport function assertTaskSelection(contract: RunContract, state: RunProjection, taskIds: readonly string[]): void {\n\tif (contract.profile !== \"linux-command-dag-v1\" || !state.inputDigest || state.candidateDigest || state.writerOpen)\n\t\tthrow new VerifiedRunError(\"task_recovery_unavailable\");\n\tfor (const id of taskIds) {\n\t\tconst task = state.tasks.find((task) => task.taskId === id);\n\t\tconst definition = contract.writer.tasks.find((task) => task.id === id);\n\t\tif (!task || !definition || (task.status !== \"failed\" && task.status !== \"running\"))\n\t\t\tthrow new VerifiedRunError(\"task_not_retryable\");\n\t\tif (task.attempt >= definition.attempts.length) throw new VerifiedRunError(\"task_attempt_limit\");\n\t}\n\tif (\n\t\tstate.tasks.some(\n\t\t\t(task) =>\n\t\t\t\ttask.generation !== state.generation || (task.status === \"running\" && !taskIds.includes(task.taskId)),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"task_selection\");\n\tif (\n\t\t!taskIds.length &&\n\t\t!readyDagTasks(contract.writer, state).length &&\n\t\t!state.tasks.every((task) => task.status === \"succeeded\")\n\t)\n\t\tthrow new VerifiedRunError(\"task_selection\");\n}\n\nexport function retryTaskProjection(\n\tcontext: WriterReduction,\n\tevent: Extract<RunEvent, { kind: \"tasks_retried\" }>,\n): readonly RunTaskProjection[] {\n\tconst { state, contract } = context;\n\tassertTaskSelection(contract, state, event.command.taskIds);\n\tif (\n\t\tevent.command.baseDigest !== state.inputDigest ||\n\t\tstate.inputDigest !== contract.workspace.baseDigest ||\n\t\tdigestObject(event.adopted) !== digestObject(taskCheckpoints(state))\n\t)\n\t\tthrow new VerifiedRunError(\"task_checkpoint_mismatch\");\n\treturn state.tasks.map(\n\t\t(task): RunTaskProjection =>\n\t\t\tevent.command.taskIds.includes(task.taskId)\n\t\t\t\t? {\n\t\t\t\t\t\ttaskId: task.taskId,\n\t\t\t\t\t\tattempt: task.attempt,\n\t\t\t\t\t\tgeneration: state.generation + 1,\n\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\tinputDigest: null,\n\t\t\t\t\t\toutputDigest: null,\n\t\t\t\t\t\tfailure: null,\n\t\t\t\t\t}\n\t\t\t\t: { ...task, generation: state.generation + 1 },\n\t);\n}\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
interface TaskIdentity {
|
|
2
|
+
readonly taskId: string;
|
|
3
|
+
readonly attempt: number;
|
|
4
|
+
readonly generation: number;
|
|
5
|
+
}
|
|
6
|
+
export type RunTaskProjection = TaskIdentity & ({
|
|
7
|
+
readonly status: "pending";
|
|
8
|
+
readonly inputDigest: null;
|
|
9
|
+
readonly outputDigest: null;
|
|
10
|
+
readonly failure: null;
|
|
11
|
+
} | {
|
|
12
|
+
readonly status: "running";
|
|
13
|
+
readonly inputDigest: string;
|
|
14
|
+
readonly outputDigest: null;
|
|
15
|
+
readonly failure: null;
|
|
16
|
+
} | {
|
|
17
|
+
readonly status: "succeeded";
|
|
18
|
+
readonly inputDigest: string;
|
|
19
|
+
readonly outputDigest: string;
|
|
20
|
+
readonly failure: null;
|
|
21
|
+
} | {
|
|
22
|
+
readonly status: "failed";
|
|
23
|
+
readonly inputDigest: string;
|
|
24
|
+
readonly outputDigest: null;
|
|
25
|
+
readonly failure: string;
|
|
26
|
+
});
|
|
27
|
+
export type RunTaskCheckpoint = Extract<RunTaskProjection, {
|
|
28
|
+
status: "succeeded";
|
|
29
|
+
}>;
|
|
30
|
+
export type DagEvent = {
|
|
31
|
+
readonly kind: "task_started";
|
|
32
|
+
readonly taskId: string;
|
|
33
|
+
readonly attempt: number;
|
|
34
|
+
readonly inputDigest: string;
|
|
35
|
+
readonly observedMs: number;
|
|
36
|
+
} | {
|
|
37
|
+
readonly kind: "task_finished";
|
|
38
|
+
readonly taskId: string;
|
|
39
|
+
readonly attempt: number;
|
|
40
|
+
readonly outputDigest: string | null;
|
|
41
|
+
readonly failure: string | null;
|
|
42
|
+
readonly observedMs: number;
|
|
43
|
+
} | {
|
|
44
|
+
readonly kind: "tasks_paused";
|
|
45
|
+
};
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=dag-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-types.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-types.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AACD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAC3C,CACG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAC/G;IACA,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACxB,CACH,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AACpF,MAAM,MAAM,QAAQ,GACjB;IACA,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC3B,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC","sourcesContent":["interface TaskIdentity {\n\treadonly taskId: string;\n\treadonly attempt: number;\n\treadonly generation: number;\n}\nexport type RunTaskProjection = TaskIdentity &\n\t(\n\t\t| { readonly status: \"pending\"; readonly inputDigest: null; readonly outputDigest: null; readonly failure: null }\n\t\t| {\n\t\t\t\treadonly status: \"running\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: null;\n\t\t\t\treadonly failure: null;\n\t\t }\n\t\t| {\n\t\t\t\treadonly status: \"succeeded\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: string;\n\t\t\t\treadonly failure: null;\n\t\t }\n\t\t| {\n\t\t\t\treadonly status: \"failed\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: null;\n\t\t\t\treadonly failure: string;\n\t\t }\n\t);\nexport type RunTaskCheckpoint = Extract<RunTaskProjection, { status: \"succeeded\" }>;\nexport type DagEvent =\n\t| {\n\t\t\treadonly kind: \"task_started\";\n\t\t\treadonly taskId: string;\n\t\t\treadonly attempt: number;\n\t\t\treadonly inputDigest: string;\n\t\t\treadonly observedMs: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"task_finished\";\n\t\t\treadonly taskId: string;\n\t\t\treadonly attempt: number;\n\t\t\treadonly outputDigest: string | null;\n\t\t\treadonly failure: string | null;\n\t\t\treadonly observedMs: number;\n\t }\n\t| { readonly kind: \"tasks_paused\" };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-types.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-types.ts"],"names":[],"mappings":"","sourcesContent":["interface TaskIdentity {\n\treadonly taskId: string;\n\treadonly attempt: number;\n\treadonly generation: number;\n}\nexport type RunTaskProjection = TaskIdentity &\n\t(\n\t\t| { readonly status: \"pending\"; readonly inputDigest: null; readonly outputDigest: null; readonly failure: null }\n\t\t| {\n\t\t\t\treadonly status: \"running\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: null;\n\t\t\t\treadonly failure: null;\n\t\t }\n\t\t| {\n\t\t\t\treadonly status: \"succeeded\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: string;\n\t\t\t\treadonly failure: null;\n\t\t }\n\t\t| {\n\t\t\t\treadonly status: \"failed\";\n\t\t\t\treadonly inputDigest: string;\n\t\t\t\treadonly outputDigest: null;\n\t\t\t\treadonly failure: string;\n\t\t }\n\t);\nexport type RunTaskCheckpoint = Extract<RunTaskProjection, { status: \"succeeded\" }>;\nexport type DagEvent =\n\t| {\n\t\t\treadonly kind: \"task_started\";\n\t\t\treadonly taskId: string;\n\t\t\treadonly attempt: number;\n\t\t\treadonly inputDigest: string;\n\t\t\treadonly observedMs: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"task_finished\";\n\t\t\treadonly taskId: string;\n\t\t\treadonly attempt: number;\n\t\t\treadonly outputDigest: string | null;\n\t\t\treadonly failure: string | null;\n\t\t\treadonly observedMs: number;\n\t }\n\t| { readonly kind: \"tasks_paused\" };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-parser.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/event-parser.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgC/C,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CA6GpD","sourcesContent":["import {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n} from \"omk-protocol\";\nimport type { RunTaskCheckpoint } from \"./dag-types.ts\";\nimport { parseNamespaceIdentity } from \"./namespace-identity.ts\";\nimport { parseRecoveryBudget } from \"./recovery-clock.ts\";\nimport type { RunEvent } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction text(value: unknown): string {\n\tif (typeof value !== \"string\" || !/^[A-Za-z0-9_-]{1,128}$/.test(value)) throw new VerifiedRunError(\"integrity\");\n\treturn value;\n}\nfunction digest(value: unknown): string {\n\tconst result = text(value);\n\tif (!/^[a-f0-9]{64}$/.test(result)) throw new VerifiedRunError(\"integrity\");\n\treturn result;\n}\nfunction integer(value: unknown): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) throw new VerifiedRunError(\"integrity\");\n\treturn value;\n}\n\nfunction checkpoint(raw: unknown): RunTaskCheckpoint {\n\tif (typeof raw !== \"object\" || raw === null) throw new VerifiedRunError(\"integrity\");\n\tconst value: Record<string, unknown> = Object.fromEntries(Object.entries(raw));\n\tif (value.status !== \"succeeded\" || value.failure !== null) throw new VerifiedRunError(\"integrity\");\n\treturn Object.freeze({\n\t\ttaskId: text(value.taskId),\n\t\tattempt: integer(value.attempt),\n\t\tgeneration: integer(value.generation),\n\t\tstatus: \"succeeded\",\n\t\tinputDigest: digest(value.inputDigest),\n\t\toutputDigest: digest(value.outputDigest),\n\t\tfailure: null,\n\t});\n}\n\nexport function parseRunEvent(raw: unknown): RunEvent {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) throw new VerifiedRunError(\"integrity\");\n\tconst value: Record<string, unknown> = Object.fromEntries(Object.entries(raw));\n\tswitch (value.kind) {\n\t\tcase \"created\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tcontract: parseRunContract(value.contract),\n\t\t\t\tcommand: parseRunStartCommand(value.command),\n\t\t\t};\n\t\tcase \"budget_anchored\":\n\t\t\tif (value.driver !== \"linux-pidns-gate-v1\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tbudget: parseRecoveryBudget(value.budget),\n\t\t\t\tenvironmentDigest: digest(value.environmentDigest),\n\t\t\t\tdriver: value.driver,\n\t\t\t};\n\t\tcase \"dispatch\": {\n\t\t\tif (value.role !== \"writer\" && value.role !== \"verifier\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\trole: value.role,\n\t\t\t\tclaimId: value.claimId === null ? null : text(value.claimId),\n\t\t\t};\n\t\t}\n\t\tcase \"input_checkpoint\":\n\t\t\treturn { kind: value.kind, digest: digest(value.digest) };\n\t\tcase \"process_ready\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\tidentity: parseNamespaceIdentity(value.identity),\n\t\t\t};\n\t\tcase \"task_started\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\ttaskId: text(value.taskId),\n\t\t\t\tattempt: integer(value.attempt),\n\t\t\t\tinputDigest: digest(value.inputDigest),\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t};\n\t\tcase \"task_finished\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\ttaskId: text(value.taskId),\n\t\t\t\tattempt: integer(value.attempt),\n\t\t\t\toutputDigest: value.outputDigest === null ? null : digest(value.outputDigest),\n\t\t\t\tfailure: value.failure === null ? null : text(value.failure),\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t};\n\t\tcase \"tasks_paused\":\n\t\tcase \"writer_opened\":\n\t\t\treturn { kind: value.kind };\n\t\tcase \"model_request\":\n\t\t\treturn { kind: value.kind, requestId: text(value.requestId) };\n\t\tcase \"writer_closed\":\n\t\t\tif (typeof value.completed !== \"boolean\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn { kind: value.kind, completed: value.completed };\n\t\tcase \"exited\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\tfailure: value.failure === null ? null : text(value.failure),\n\t\t\t};\n\t\tcase \"candidate\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tdigest: digest(value.digest),\n\t\t\t\t...(value.observedMs === undefined ? {} : { observedMs: integer(value.observedMs) }),\n\t\t\t\t...(value.verificationDeadlineMs === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { verificationDeadlineMs: integer(value.verificationDeadlineMs) }),\n\t\t\t};\n\t\tcase \"resumed\":\n\t\tcase \"tasks_retried\":\n\t\tcase \"writer_restarted\": {\n\t\t\tif (!Array.isArray(value.reconciledExecutionIds) || value.reconciledExecutionIds.length > 128)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\tconst fields = {\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t\treconciledExecutionIds: Object.freeze(value.reconciledExecutionIds.map(text)),\n\t\t\t};\n\t\t\tswitch (value.kind) {\n\t\t\t\tcase \"resumed\":\n\t\t\t\t\treturn { ...fields, kind: value.kind, command: parseRunResumeCommand(value.command) };\n\t\t\t\tcase \"writer_restarted\":\n\t\t\t\t\treturn { ...fields, kind: value.kind, command: parseRunWriterRestartCommand(value.command) };\n\t\t\t\tcase \"tasks_retried\":\n\t\t\t\t\tif (!Array.isArray(value.adopted) || value.adopted.length > 16) throw new VerifiedRunError(\"integrity\");\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...fields,\n\t\t\t\t\t\tkind: value.kind,\n\t\t\t\t\t\tcommand: parseRunTaskRetryCommand(value.command),\n\t\t\t\t\t\tadopted: Object.freeze(value.adopted.map(checkpoint)),\n\t\t\t\t\t};\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t}\n\t\t}\n\t\tcase \"evaluated\":\n\t\t\tif (typeof value.verified !== \"boolean\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn { kind: value.kind, receiptDigest: digest(value.receiptDigest), verified: value.verified };\n\t\tcase \"failed\":\n\t\t\treturn { kind: value.kind, code: text(value.code) };\n\t\tdefault:\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { parseRunContract, parseRunResumeCommand, parseRunStartCommand, parseRunTaskRetryCommand, parseRunWriterRestartCommand, } from "omk-protocol";
|
|
2
|
+
import { parseNamespaceIdentity } from "./namespace-identity.js";
|
|
3
|
+
import { parseRecoveryBudget } from "./recovery-clock.js";
|
|
4
|
+
import { VerifiedRunError } from "./storage.js";
|
|
5
|
+
function text(value) {
|
|
6
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(value))
|
|
7
|
+
throw new VerifiedRunError("integrity");
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function digest(value) {
|
|
11
|
+
const result = text(value);
|
|
12
|
+
if (!/^[a-f0-9]{64}$/.test(result))
|
|
13
|
+
throw new VerifiedRunError("integrity");
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
function integer(value) {
|
|
17
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
|
|
18
|
+
throw new VerifiedRunError("integrity");
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function checkpoint(raw) {
|
|
22
|
+
if (typeof raw !== "object" || raw === null)
|
|
23
|
+
throw new VerifiedRunError("integrity");
|
|
24
|
+
const value = Object.fromEntries(Object.entries(raw));
|
|
25
|
+
if (value.status !== "succeeded" || value.failure !== null)
|
|
26
|
+
throw new VerifiedRunError("integrity");
|
|
27
|
+
return Object.freeze({
|
|
28
|
+
taskId: text(value.taskId),
|
|
29
|
+
attempt: integer(value.attempt),
|
|
30
|
+
generation: integer(value.generation),
|
|
31
|
+
status: "succeeded",
|
|
32
|
+
inputDigest: digest(value.inputDigest),
|
|
33
|
+
outputDigest: digest(value.outputDigest),
|
|
34
|
+
failure: null,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function parseRunEvent(raw) {
|
|
38
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
39
|
+
throw new VerifiedRunError("integrity");
|
|
40
|
+
const value = Object.fromEntries(Object.entries(raw));
|
|
41
|
+
switch (value.kind) {
|
|
42
|
+
case "created":
|
|
43
|
+
return {
|
|
44
|
+
kind: value.kind,
|
|
45
|
+
contract: parseRunContract(value.contract),
|
|
46
|
+
command: parseRunStartCommand(value.command),
|
|
47
|
+
};
|
|
48
|
+
case "budget_anchored":
|
|
49
|
+
if (value.driver !== "linux-pidns-gate-v1")
|
|
50
|
+
throw new VerifiedRunError("integrity");
|
|
51
|
+
return {
|
|
52
|
+
kind: value.kind,
|
|
53
|
+
budget: parseRecoveryBudget(value.budget),
|
|
54
|
+
environmentDigest: digest(value.environmentDigest),
|
|
55
|
+
driver: value.driver,
|
|
56
|
+
};
|
|
57
|
+
case "dispatch": {
|
|
58
|
+
if (value.role !== "writer" && value.role !== "verifier")
|
|
59
|
+
throw new VerifiedRunError("integrity");
|
|
60
|
+
return {
|
|
61
|
+
kind: value.kind,
|
|
62
|
+
executionId: text(value.executionId),
|
|
63
|
+
role: value.role,
|
|
64
|
+
claimId: value.claimId === null ? null : text(value.claimId),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
case "input_checkpoint":
|
|
68
|
+
return { kind: value.kind, digest: digest(value.digest) };
|
|
69
|
+
case "process_ready":
|
|
70
|
+
return {
|
|
71
|
+
kind: value.kind,
|
|
72
|
+
executionId: text(value.executionId),
|
|
73
|
+
identity: parseNamespaceIdentity(value.identity),
|
|
74
|
+
};
|
|
75
|
+
case "task_started":
|
|
76
|
+
return {
|
|
77
|
+
kind: value.kind,
|
|
78
|
+
taskId: text(value.taskId),
|
|
79
|
+
attempt: integer(value.attempt),
|
|
80
|
+
inputDigest: digest(value.inputDigest),
|
|
81
|
+
observedMs: integer(value.observedMs),
|
|
82
|
+
};
|
|
83
|
+
case "task_finished":
|
|
84
|
+
return {
|
|
85
|
+
kind: value.kind,
|
|
86
|
+
taskId: text(value.taskId),
|
|
87
|
+
attempt: integer(value.attempt),
|
|
88
|
+
outputDigest: value.outputDigest === null ? null : digest(value.outputDigest),
|
|
89
|
+
failure: value.failure === null ? null : text(value.failure),
|
|
90
|
+
observedMs: integer(value.observedMs),
|
|
91
|
+
};
|
|
92
|
+
case "tasks_paused":
|
|
93
|
+
case "writer_opened":
|
|
94
|
+
return { kind: value.kind };
|
|
95
|
+
case "model_request":
|
|
96
|
+
return { kind: value.kind, requestId: text(value.requestId) };
|
|
97
|
+
case "writer_closed":
|
|
98
|
+
if (typeof value.completed !== "boolean")
|
|
99
|
+
throw new VerifiedRunError("integrity");
|
|
100
|
+
return { kind: value.kind, completed: value.completed };
|
|
101
|
+
case "exited":
|
|
102
|
+
return {
|
|
103
|
+
kind: value.kind,
|
|
104
|
+
executionId: text(value.executionId),
|
|
105
|
+
failure: value.failure === null ? null : text(value.failure),
|
|
106
|
+
};
|
|
107
|
+
case "candidate":
|
|
108
|
+
return {
|
|
109
|
+
kind: value.kind,
|
|
110
|
+
digest: digest(value.digest),
|
|
111
|
+
...(value.observedMs === undefined ? {} : { observedMs: integer(value.observedMs) }),
|
|
112
|
+
...(value.verificationDeadlineMs === undefined
|
|
113
|
+
? {}
|
|
114
|
+
: { verificationDeadlineMs: integer(value.verificationDeadlineMs) }),
|
|
115
|
+
};
|
|
116
|
+
case "resumed":
|
|
117
|
+
case "tasks_retried":
|
|
118
|
+
case "writer_restarted": {
|
|
119
|
+
if (!Array.isArray(value.reconciledExecutionIds) || value.reconciledExecutionIds.length > 128)
|
|
120
|
+
throw new VerifiedRunError("integrity");
|
|
121
|
+
const fields = {
|
|
122
|
+
observedMs: integer(value.observedMs),
|
|
123
|
+
reconciledExecutionIds: Object.freeze(value.reconciledExecutionIds.map(text)),
|
|
124
|
+
};
|
|
125
|
+
switch (value.kind) {
|
|
126
|
+
case "resumed":
|
|
127
|
+
return { ...fields, kind: value.kind, command: parseRunResumeCommand(value.command) };
|
|
128
|
+
case "writer_restarted":
|
|
129
|
+
return { ...fields, kind: value.kind, command: parseRunWriterRestartCommand(value.command) };
|
|
130
|
+
case "tasks_retried":
|
|
131
|
+
if (!Array.isArray(value.adopted) || value.adopted.length > 16)
|
|
132
|
+
throw new VerifiedRunError("integrity");
|
|
133
|
+
return {
|
|
134
|
+
...fields,
|
|
135
|
+
kind: value.kind,
|
|
136
|
+
command: parseRunTaskRetryCommand(value.command),
|
|
137
|
+
adopted: Object.freeze(value.adopted.map(checkpoint)),
|
|
138
|
+
};
|
|
139
|
+
default:
|
|
140
|
+
throw new VerifiedRunError("integrity");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
case "evaluated":
|
|
144
|
+
if (typeof value.verified !== "boolean")
|
|
145
|
+
throw new VerifiedRunError("integrity");
|
|
146
|
+
return { kind: value.kind, receiptDigest: digest(value.receiptDigest), verified: value.verified };
|
|
147
|
+
case "failed":
|
|
148
|
+
return { kind: value.kind, code: text(value.code) };
|
|
149
|
+
default:
|
|
150
|
+
throw new VerifiedRunError("integrity");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=event-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-parser.js","sourceRoot":"","sources":["../../../src/core/verified-run/event-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n} from \"omk-protocol\";\nimport type { RunTaskCheckpoint } from \"./dag-types.ts\";\nimport { parseNamespaceIdentity } from \"./namespace-identity.ts\";\nimport { parseRecoveryBudget } from \"./recovery-clock.ts\";\nimport type { RunEvent } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction text(value: unknown): string {\n\tif (typeof value !== \"string\" || !/^[A-Za-z0-9_-]{1,128}$/.test(value)) throw new VerifiedRunError(\"integrity\");\n\treturn value;\n}\nfunction digest(value: unknown): string {\n\tconst result = text(value);\n\tif (!/^[a-f0-9]{64}$/.test(result)) throw new VerifiedRunError(\"integrity\");\n\treturn result;\n}\nfunction integer(value: unknown): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) throw new VerifiedRunError(\"integrity\");\n\treturn value;\n}\n\nfunction checkpoint(raw: unknown): RunTaskCheckpoint {\n\tif (typeof raw !== \"object\" || raw === null) throw new VerifiedRunError(\"integrity\");\n\tconst value: Record<string, unknown> = Object.fromEntries(Object.entries(raw));\n\tif (value.status !== \"succeeded\" || value.failure !== null) throw new VerifiedRunError(\"integrity\");\n\treturn Object.freeze({\n\t\ttaskId: text(value.taskId),\n\t\tattempt: integer(value.attempt),\n\t\tgeneration: integer(value.generation),\n\t\tstatus: \"succeeded\",\n\t\tinputDigest: digest(value.inputDigest),\n\t\toutputDigest: digest(value.outputDigest),\n\t\tfailure: null,\n\t});\n}\n\nexport function parseRunEvent(raw: unknown): RunEvent {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) throw new VerifiedRunError(\"integrity\");\n\tconst value: Record<string, unknown> = Object.fromEntries(Object.entries(raw));\n\tswitch (value.kind) {\n\t\tcase \"created\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tcontract: parseRunContract(value.contract),\n\t\t\t\tcommand: parseRunStartCommand(value.command),\n\t\t\t};\n\t\tcase \"budget_anchored\":\n\t\t\tif (value.driver !== \"linux-pidns-gate-v1\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tbudget: parseRecoveryBudget(value.budget),\n\t\t\t\tenvironmentDigest: digest(value.environmentDigest),\n\t\t\t\tdriver: value.driver,\n\t\t\t};\n\t\tcase \"dispatch\": {\n\t\t\tif (value.role !== \"writer\" && value.role !== \"verifier\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\trole: value.role,\n\t\t\t\tclaimId: value.claimId === null ? null : text(value.claimId),\n\t\t\t};\n\t\t}\n\t\tcase \"input_checkpoint\":\n\t\t\treturn { kind: value.kind, digest: digest(value.digest) };\n\t\tcase \"process_ready\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\tidentity: parseNamespaceIdentity(value.identity),\n\t\t\t};\n\t\tcase \"task_started\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\ttaskId: text(value.taskId),\n\t\t\t\tattempt: integer(value.attempt),\n\t\t\t\tinputDigest: digest(value.inputDigest),\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t};\n\t\tcase \"task_finished\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\ttaskId: text(value.taskId),\n\t\t\t\tattempt: integer(value.attempt),\n\t\t\t\toutputDigest: value.outputDigest === null ? null : digest(value.outputDigest),\n\t\t\t\tfailure: value.failure === null ? null : text(value.failure),\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t};\n\t\tcase \"tasks_paused\":\n\t\tcase \"writer_opened\":\n\t\t\treturn { kind: value.kind };\n\t\tcase \"model_request\":\n\t\t\treturn { kind: value.kind, requestId: text(value.requestId) };\n\t\tcase \"writer_closed\":\n\t\t\tif (typeof value.completed !== \"boolean\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn { kind: value.kind, completed: value.completed };\n\t\tcase \"exited\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\texecutionId: text(value.executionId),\n\t\t\t\tfailure: value.failure === null ? null : text(value.failure),\n\t\t\t};\n\t\tcase \"candidate\":\n\t\t\treturn {\n\t\t\t\tkind: value.kind,\n\t\t\t\tdigest: digest(value.digest),\n\t\t\t\t...(value.observedMs === undefined ? {} : { observedMs: integer(value.observedMs) }),\n\t\t\t\t...(value.verificationDeadlineMs === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { verificationDeadlineMs: integer(value.verificationDeadlineMs) }),\n\t\t\t};\n\t\tcase \"resumed\":\n\t\tcase \"tasks_retried\":\n\t\tcase \"writer_restarted\": {\n\t\t\tif (!Array.isArray(value.reconciledExecutionIds) || value.reconciledExecutionIds.length > 128)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\tconst fields = {\n\t\t\t\tobservedMs: integer(value.observedMs),\n\t\t\t\treconciledExecutionIds: Object.freeze(value.reconciledExecutionIds.map(text)),\n\t\t\t};\n\t\t\tswitch (value.kind) {\n\t\t\t\tcase \"resumed\":\n\t\t\t\t\treturn { ...fields, kind: value.kind, command: parseRunResumeCommand(value.command) };\n\t\t\t\tcase \"writer_restarted\":\n\t\t\t\t\treturn { ...fields, kind: value.kind, command: parseRunWriterRestartCommand(value.command) };\n\t\t\t\tcase \"tasks_retried\":\n\t\t\t\t\tif (!Array.isArray(value.adopted) || value.adopted.length > 16) throw new VerifiedRunError(\"integrity\");\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...fields,\n\t\t\t\t\t\tkind: value.kind,\n\t\t\t\t\t\tcommand: parseRunTaskRetryCommand(value.command),\n\t\t\t\t\t\tadopted: Object.freeze(value.adopted.map(checkpoint)),\n\t\t\t\t\t};\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t}\n\t\t}\n\t\tcase \"evaluated\":\n\t\t\tif (typeof value.verified !== \"boolean\") throw new VerifiedRunError(\"integrity\");\n\t\t\treturn { kind: value.kind, receiptDigest: digest(value.receiptDigest), verified: value.verified };\n\t\tcase \"failed\":\n\t\t\treturn { kind: value.kind, code: text(value.code) };\n\t\tdefault:\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { parseRunEvent } from \"./event-parser.ts\";\nexport { projectRun } from \"./projection.ts\";\nexport type { RunEvent, RunProjection } from \"./run-types.ts\";\n"]}
|