1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! The Salvor graph document format, strict versioned validation, and JSON
//! Schema emission.
//!
//! A graph is a declarative CONTROL document: authored once, submitted, hashed
//! into a run, and then frozen. It coordinates nodes the runtime already knows
//! how to execute (a full `agent` loop, a single `tool` call, a human `gate`, a
//! `branch`, a `map` fan-out, and a `fold` bounded-iteration loop) and the typed
//! edges between them. This crate owns four things and no more:
//!
//! - the [`document`] model: [`Graph`], [`Node`], the payloads, and [`Edge`],
//! parsed strictly (unknown fields rejected) and versioned additively;
//! - the [`validate`] pass: a set of independent checks that collect every
//! error and name the offending node or edge;
//! - the [`expr`] language: the total, non-Turing-complete condition language a
//! `branch` case's expression string is written in, parsed at the submit
//! boundary so a malformed condition is a node-precise error, never a runtime
//! failure;
//! - [`graph_schema`]: the graph document's JSON Schema, the single source of
//! truth for editors and the future per-language builders.
//!
//! # What this crate is NOT
//!
//! There is no run-time execution here. No engine drives a graph, no scheduler
//! fans out a `map`, and no server endpoint submits one. Validation PARSES a
//! branch condition (so a bad one fails at submit) but never EVALUATES one
//! against a routed value; the evaluator [`expr::Expr::eval`] exists and is
//! total, but it is the future engine that calls it, not this crate. Keeping
//! this crate to format-plus-validation is what keeps it a pure, IO-free leaf:
//! it depends only on `serde`, `serde_json`, `schemars`, and `thiserror`, drags
//! in no runtime, and so stays usable from a future wasm dashboard projection.
//!
//! # Strict in, additive out
//!
//! Parsing rejects a stray field loudly, because a silently dropped field could
//! drop a gate or an unenforced budget. Validation is likewise strict and fails
//! at the submit boundary, not at run time. The one forward-compatibility
//! concession is the additive `schema_version` discipline (see
//! [`document::SCHEMA_VERSION`]): a graph recorded under an older build still
//! parses and validates under a newer one.
pub use ;
pub use ;
pub use ;
pub use ;
/// Returns the graph document's JSON Schema as a [`serde_json::Value`].
///
/// This is the single source of truth for the document format: editors read it
/// for autocomplete and inline validation, and the future per-language builders
/// generate from it so a Rust, Python, or TypeScript author reduces to the same
/// canonical JSON. It is derived from the [`Graph`] types by `schemars`, so it
/// can never drift from what this crate actually parses.