Skip to content
Merged
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ Full diagram and concurrency model: [docs/dev/architecture.md](docs/dev/architec
| Diff / change feed (`diff_between`, `diff_commits`) | [docs/user/branching/changes.md](docs/user/branching/changes.md) |
| Query execution, mutation execution, bulk loader, `load` vs `ingest` | [docs/dev/execution.md](docs/dev/execution.md) |
| `optimize` (compaction) and `cleanup` (version GC) | [docs/user/operations/maintenance.md](docs/user/operations/maintenance.md) |
| Upgrade across a storage-format change (export/import rebuild) | [docs/user/operations/upgrade.md](docs/user/operations/upgrade.md) |
| Versioning & compatibility policy (release / wire / storage strict-single-version / Lance) | [docs/dev/versioning.md](docs/dev/versioning.md) |
| Cluster operator guide (deploy/manage clusters, approvals, recovery, serving) | [docs/user/clusters/index.md](docs/user/clusters/index.md) |
| Cedar policy actions, scopes, CLI | [docs/user/operations/policy.md](docs/user/operations/policy.md) |
| HTTP server endpoints, auth, error model, body limits | [docs/user/operations/server.md](docs/user/operations/server.md) |
Expand Down Expand Up @@ -263,7 +265,7 @@ omnigraph policy explain --cluster ./company-brain --graph knowledge --actor act
| Schema language | — | `.pg` + Pest grammar + catalog + interfaces + constraints + annotations |
| Query language | — | `.gq` + Pest grammar + IR + lowering + linter |
| Schema migration planning | — | `plan_schema_migration` + `apply_schema` step types + `__schema_apply_lock__` |
| Commit graph (DAG) across whole graph | — | Lineage (linear + merge parents, ULID ids, actor) stored as `graph_commit`/`graph_head` rows in `__manifest`, written in the same publish CAS as the table-version rows (RFC-013 Phase 7 — no separate `_graph_commits.lance` write; manifest→commit-graph atomicity gap closed); the in-memory commit graph is a projection of those rows |
| Commit graph (DAG) across whole graph | — | Lineage (linear + merge parents, ULID ids, actor) stored as `graph_commit`/`graph_head` rows in `__manifest`, written in the same publish CAS as the table-version rows (RFC-013 Phase 7 — atomic with the graph commit). The in-memory commit graph is a pure projection of those rows; the legacy `_graph_commits.lance` / `_graph_commit_actors.lance` tables are **retired** (a fresh graph creates neither) |
| Per-query atomic writes | — | In-memory `MutationStaging.pending` accumulator + `stage_*` / `commit_staged` per touched table at end-of-query + publisher CAS via `commit_with_expected` (single manifest commit per `mutate_as` / `load`); D₂ parse-time rule keeps inserts/updates and deletes from mixing |
| Three-way row-level merge | — | `OrderedTableCursor` + `StagedTableWriter`, structured `MergeConflictKind` |
| Change feeds | — | `diff_between` / `diff_commits` with manifest fast path + ID streaming |
Expand Down
12 changes: 11 additions & 1 deletion crates/omnigraph-api-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub struct SnapshotTableOutput {
pub struct SnapshotOutput {
pub branch: String,
pub manifest_version: u64,
/// The on-disk internal-schema (storage-format) version this graph's branch
/// is stamped at.
pub internal_schema_version: u32,
pub tables: Vec<SnapshotTableOutput>,
}

Expand Down Expand Up @@ -538,6 +541,8 @@ pub struct CommitListQuery {
pub struct HealthOutput {
pub status: String,
pub version: String,
/// The internal-schema (storage-format) version this binary writes and reads.
pub internal_schema_version: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_version: Option<String>,
}
Expand Down Expand Up @@ -587,7 +592,11 @@ pub struct ErrorOutput {
pub manifest_conflict: Option<ManifestConflictOutput>,
}

pub fn snapshot_payload(branch: &str, snapshot: &Snapshot) -> SnapshotOutput {
pub fn snapshot_payload(
branch: &str,
snapshot: &Snapshot,
internal_schema_version: u32,
) -> SnapshotOutput {
let mut entries: Vec<_> = snapshot.entries().cloned().collect();
entries.sort_by(|a, b| a.table_key.cmp(&b.table_key));
let tables = entries
Expand All @@ -603,6 +612,7 @@ pub fn snapshot_payload(branch: &str, snapshot: &Snapshot) -> SnapshotOutput {
SnapshotOutput {
branch: branch.to_string(),
manifest_version: snapshot.version(),
internal_schema_version,
tables,
}
}
Expand Down
5 changes: 4 additions & 1 deletion crates/omnigraph-cli/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,10 @@ impl GraphClient {
GraphClient::Embedded { uri, .. } => {
let db = Omnigraph::open(uri).await?;
let snapshot = db.snapshot_of(ReadTarget::branch(branch)).await?;
Ok(snapshot_payload(branch, &snapshot))
let internal_schema_version = db
.internal_schema_version_of(ReadTarget::branch(branch))
.await?;
Ok(snapshot_payload(branch, &snapshot, internal_schema_version))
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion crates/omnigraph-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ async fn main() -> Result<()> {
}
Command::Version => {
println!("omnigraph {}", env!("CARGO_PKG_VERSION"));
println!(
"internal-schema {}",
omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION
);
}
Command::Embed(args) => {
let output = execute_embed(&args).await?;
Expand Down Expand Up @@ -613,7 +617,12 @@ async fn main() -> Result<()> {
if json {
print_json(&payload)?;
} else {
print_snapshot_human(&payload.branch, payload.manifest_version, &payload.tables);
print_snapshot_human(
&payload.branch,
payload.manifest_version,
payload.internal_schema_version,
&payload.tables,
);
}
}
Command::Export {
Expand Down
8 changes: 7 additions & 1 deletion crates/omnigraph-cli/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,9 +732,15 @@ pub(crate) fn print_embed_human(output: &EmbedOutput) {
);
}

pub(crate) fn print_snapshot_human(branch: &str, manifest_version: u64, entries: &[SnapshotTableOutput]) {
pub(crate) fn print_snapshot_human(
branch: &str,
manifest_version: u64,
internal_schema_version: u32,
entries: &[SnapshotTableOutput],
) {
println!("branch: {}", branch);
println!("manifest_version: {}", manifest_version);
println!("internal_schema_version: {}", internal_schema_version);
for entry in entries {
println!(
"{} v{} branch={} rows={}",
Expand Down
8 changes: 8 additions & 0 deletions crates/omnigraph-cli/tests/cli_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,10 @@ fn snapshot_json_returns_manifest_version_and_tables() {
payload["manifest_version"].as_u64().unwrap(),
manifest_dataset_version(&graph)
);
assert_eq!(
payload["internal_schema_version"].as_u64().unwrap(),
u64::from(omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION)
);
assert!(payload["tables"].as_array().unwrap().len() >= 4);
}

Expand Down Expand Up @@ -1947,6 +1951,10 @@ fn snapshot_human_output_includes_branch_and_table_summaries() {

assert!(stdout.contains("branch: main"));
assert!(stdout.contains("manifest_version:"));
assert!(stdout.contains(&format!(
"internal_schema_version: {}",
omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION
)));
assert!(stdout.contains("node:Person v"));
assert!(stdout.contains("edge:Knows v"));
}
Expand Down
13 changes: 10 additions & 3 deletions crates/omnigraph-cli/tests/cli_schema_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ fn version_command_prints_current_cli_version() {
let output = output_success(cli().arg("version"));
let stdout = stdout_string(&output);

assert_eq!(
stdout.trim(),
format!("omnigraph {}", env!("CARGO_PKG_VERSION"))
assert!(
stdout.contains(&format!("omnigraph {}", env!("CARGO_PKG_VERSION"))),
"version output must include the CLI version line, got: {stdout}"
);
assert!(
stdout.contains(&format!(
"internal-schema {}",
omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION
)),
"version output must include the internal-schema line, got: {stdout}"
);
}

Expand Down
19 changes: 15 additions & 4 deletions crates/omnigraph-server/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) async fn server_health() -> Json<HealthOutput> {
Json(HealthOutput {
status: "ok".to_string(),
version: SERVER_VERSION.to_string(),
internal_schema_version: SERVER_INTERNAL_SCHEMA_VERSION,
source_version: SERVER_SOURCE_VERSION.map(str::to_string),
})
}
Expand Down Expand Up @@ -459,13 +460,23 @@ pub(crate) async fn server_snapshot(
target_branch: None,
},
)?;
let snapshot = {
let (snapshot, internal_schema_version) = {
let db = &handle.engine;
db.snapshot_of(ReadTarget::branch(branch.as_str()))
let snapshot = db
.snapshot_of(ReadTarget::branch(branch.as_str()))
.await
.map_err(ApiError::from_omni)?
.map_err(ApiError::from_omni)?;
let internal_schema_version = db
.internal_schema_version_of(ReadTarget::branch(branch.as_str()))
.await
.map_err(ApiError::from_omni)?;
(snapshot, internal_schema_version)
};
Ok(Json(snapshot_payload(&branch, &snapshot)))
Ok(Json(snapshot_payload(
&branch,
&snapshot,
internal_schema_version,
)))
}

/// Header values that flag a response as coming from a deprecated route
Expand Down
3 changes: 3 additions & 0 deletions crates/omnigraph-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ const DEFAULT_REQUEST_BODY_LIMIT_BYTES: usize = 1_048_576;
const INGEST_REQUEST_BODY_LIMIT_BYTES: usize = 32 * 1024 * 1024;
const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION");
const SERVER_SOURCE_VERSION: Option<&str> = option_env!("OMNIGRAPH_SOURCE_VERSION");
/// The internal-schema (storage-format) version this binary writes and reads.
const SERVER_INTERNAL_SCHEMA_VERSION: u32 =
omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION;

#[derive(Debug, Clone)]
pub struct ServerConfig {
Expand Down
4 changes: 4 additions & 0 deletions crates/omnigraph-server/tests/auth_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ async fn healthz_succeeds_after_startup() {
assert_eq!(status, StatusCode::OK);
assert_eq!(body["status"], "ok");
assert_eq!(body["version"], env!("CARGO_PKG_VERSION"));
assert_eq!(
body["internal_schema_version"].as_u64().unwrap(),
u64::from(omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION)
);
match option_env!("OMNIGRAPH_SOURCE_VERSION") {
Some(source_version) => assert_eq!(body["source_version"], source_version),
None => assert!(body.get("source_version").is_none()),
Expand Down
4 changes: 4 additions & 0 deletions crates/omnigraph-server/tests/data_routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ async fn snapshot_route_returns_manifest_dataset_version() {
snapshot_body["manifest_version"].as_u64().unwrap(),
expected_manifest_version
);
assert_eq!(
snapshot_body["internal_schema_version"].as_u64().unwrap(),
u64::from(omnigraph::db::manifest::INTERNAL_MANIFEST_SCHEMA_VERSION)
);
assert!(snapshot_body["tables"].is_array());
}

Expand Down
2 changes: 2 additions & 0 deletions crates/omnigraph-server/tests/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ fn health_output_schema_has_expected_fields() {
let props = schema["properties"].as_object().unwrap();
assert!(props.contains_key("status"));
assert!(props.contains_key("version"));
assert!(props.contains_key("internal_schema_version"));
assert!(props.contains_key("source_version"));
}

Expand Down Expand Up @@ -644,6 +645,7 @@ fn snapshot_output_schema_has_expected_fields() {
let props = schema["properties"].as_object().unwrap();
assert!(props.contains_key("branch"));
assert!(props.contains_key("manifest_version"));
assert!(props.contains_key("internal_schema_version"));
assert!(props.contains_key("tables"));
}

Expand Down
Loading