OmniGraph v0.9.0
A substrate and durability release. Lance reaches 9.0.0 stable; the write
path gains rename-stable schema identity, key-conflict fencing, and crash
recovery for every writer; the query language reaches edge properties and
pushes filters down to the scanner.
This release changes the on-disk format — v0.8.x graphs must be rebuilt
via export/import (see Upgrade notes and
docs/user/operations/upgrade.md).
Channel note: binaries ship via the installer, Homebrew, Docker, and
GitHub Releases. Registry publication did not resume in this release: access
to the crates.io account owning the historical omnigraph-* crate names was
lost, so those names are frozen at their 0.8.0 versions and should not be
used. OmniGraph returns to crates.io in 0.9.1 as a single crate,
omnigraph-db.
Highlights
-
Lance 9.0.0 stable. The prerelease git-rev pin is retired for registry
versions. File format and dependency floors are unchanged (stable V2_2
files; Arrow 58, DataFusion 54); validated against all 35 upstream commits
since the pinned release candidate plus the full test matrix. -
Schema identity survives renames. Renaming a type is a metadata-only
migration keeping the dataset, path, version history, and indexes.
Drop-and-re-add remains a new lifetime. Identity is never inferred from a
name, path, or version. -
Key-conflict fencing. Every node and edge table declares its
idas the
substrate's primary key; every insert and upsert is fenced on it. A strict
insert colliding with an existing key fails with a typedKeyConflict.
Merging a provably insert-only branch skips the target join entirely. -
Crash recovery for every writer. Mutations, loads, schema applies,
branch merges, index builds, andoptimizerecord a durable recovery intent
before their first durable effect. An interrupted write rolls forward or
compensates on the next read-write open, all-or-nothing; ambiguity fails
closed asRecoveryRequired. -
Edge properties are queryable.
$src $w:EDGE_NAME $dst(undirected
$a $w:<related> $b) binds the matched edge row, so edge properties work in
filters, projections, aggregates, and ordering —$w.confidence = "asserted",return { $w.role }. A bound traversal returns one row per
edge, keeping parallel edges distinct; unbound traversals keep set
semantics. Invalid bindings are rejected at typecheck (T23). -
Filters push down to the scanner. Standalone filter clauses — the only
form that can express ranges ($d.priority <= 2) — now push down like
inline props already did: filterednearest()returns the top-limitof
the matching rows, and filtered scans stop materializing every row (peak
memory on a filtered 1M-row scan: 2,680 MiB → 156 MiB). Filters that cannot
push down keep their previous in-memory behavior. -
branch merge --delete-branch. Deletes the source branch on a
successful merge; also a field on the endpoint. -
Container images on release.
omnigraph-serverships to GHCR and
Docker Hub. -
Faster uniqueness checks on bulk writes. Committed
@uniqueprobes
batch per constraint group — one filtered scan per 8,192-key chunk instead
of one per row. -
Bounded graph-batch ingestion. CLI, HTTP, and SDK bulk ingestion use the
ordinary actor-aware Load path: one graph commit per request, acknowledged
only after it is visible. The experimental RFC-026 write-ahead path was
rejected and is not in this release. -
Bounded streaming export. Served export pins one immutable graph cut and
streams hard-capped 64 KiB JSONL chunks through a bounded queue — no
whole-export buffering, authorization before success headers.
Behavior changes
-
Commit listings are newest-first (
commit list,GET /commits, SDK),
matching the documented contract. Omittingbranchlists main's history. -
load --mode appendis strict on existing ids — a duplicate id is a key
conflict, not an absorbed upsert. Use--mode mergefor upserts. -
Keyed writes are bounded. One
mutateor keyedloadstages at most
8,192 rows / 32 MiB per table, refused up front with
ResourceLimitExceeded(HTTP 413).--mode overwriteis a whole-table
replacement and is not row-capped. -
Cluster policy is validated strictly. Unknown YAML fields are errors;
one runtime kind per bundle; one owning bundle per scope; no branch scopes
on server actions. Configs that relied on ignored fields now fail loudly. -
CLI scope flags are validated per verb — a flag a command never reads is
rejected instead of silently ignored. -
graphs listresolves against the server registry and no longer
requires--graph. -
GET /commitswithoutbranchauthorizes asmain, exactly like the
explicit form.
Upgrade notes
- Opening a v0.8.x graph is refused with a message naming the exact commands.
Recipe: export with a 0.8.x binary,inita different root with 0.9.x,
load --mode overwrite. Data, vectors, and blobs are preserved; commit
history and branches are not. Keep the old root untouched through the
rollback window. - Server deployments: pull the graph from the serving set, rebuild offline,
repoint viacluster apply. - Downgrade is not possible — a 0.8.x binary refuses a 0.9.x graph by design.
Developer-facing
- The workspace builds from registry dependencies only; a source guard fails
if a git dependency returns. - One write protocol: every graph-content, schema, and maintenance transition
becomes authoritative at a single manifest publish, with exact pre-minted
transaction identities. See docs/dev/writes.md. - Cross-version rebuild tests run against genuine older binaries, including
the immediately preceding format. - RFC-030 (graph change feed) is published with its first internal groundwork;
no public feed API ships. RFC-031/032 (cost and correctness harnesses) are
drafts. - The workspace carries a uniform
rustfmtbaseline.