# grit
[](https://github.com/bofeizhu/grit/actions/workflows/ci.yml)
An embedded, **bi-temporal property graph for agent memory**. One SQLite
file, in-process, written in Rust. No server, no daemon, no network — compiles
for macOS, Windows, Linux, iOS, and Android.
grit is Layer 1 of a three-layer agent-memory stack: it does deterministic
graph **storage and hybrid retrieval** only. Entity extraction and dedup
judgment (Layer 2) and the agent harness (Layer 3) live elsewhere. The full
design contract — invariants, scope limits, testing bar — is in
[AGENTS.md](AGENTS.md) and is binding for anyone (human or agent) working here.
## What works today (v0.1 core)
- **Append-only, bi-temporal writes.** Every mutation is a `GraphOp` recorded
in an op-log; graph tables are derived state in the same transaction. Edges
carry event time (`valid_at`/`invalid_at`) and system time
(`created_at`/`expired_at`); invalidations are belief-versioned, so
*"what did I believe in March?"* is a query (`as_at`), not archaeology.
- **Sync-ready semantics before sync exists.** UUIDv7 keys, hybrid logical
clocks, and op application that is idempotent and commutative for
concurrent ops — property-tested across adversarial interleavings
(merge cycles, purges racing adds, out-of-order invalidations).
- **Hybrid retrieval.** FTS5 BM25 + sqlite-vec cosine + validity-filtered
graph expansion, fused with reciprocal rank fusion, returned with episode
provenance under an item/token budget.
- **Merge & forget.** `MergeNodes` executes Layer 2's dedup decisions
(cycle-safe canonical resolution); `Purge` is the only destructive op —
exact-id, tombstoned, audited in the op-log.
- **Data outlives the library.** Lossless JSONL export/import of the full
graph + oplog (`grit-cli export/import`).
```rust
use grit_core::{Budget, GraphOp, Grit, Options, Query, Traversal};
let g = Grit::open("memory.db", Options::new("laptop"))?;
g.apply(GraphOp::AddEpisode { /* … */ })?;
let hits = g.search(Query::text("exactness").group("algebra").budget(Budget::items(20)))?;
let ctx = g.traverse(&[node_id], &Traversal::default().depth(2))?;
let past = g.node_history(node_id)?; // bi-temporal audit
```
## Workspace
| `grit-core` | Schema, oplog writer actor, traversal, hybrid search — the product |
| `grit-compat` | Parked, fail-loud Graphiti/FalkorDB-dialect template-translator stub (see the re-scoped compatibility section in AGENTS.md) |
| `grit-cli` | Dev tool: import/export, stats, ad-hoc search/traverse |
Planned next (see AGENTS.md): the Rust port of Graphiti's extraction pipeline
(Layer 2, separate repo) validated by golden-trace fixtures captured from
Python Graphiti + FalkorDB. A Python `GritDriver` for upstream Graphiti is
deferred — an optional adoption play, not a milestone.
## Commands
```bash
cargo build --workspace
cargo test --workspace # unit + property + crash + migration + plan-pinning tests
cargo test -p grit-core --release --test envelope -- --ignored # latency tripwire
cargo bench -p grit-core --bench hot_paths # criterion (precision)
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all
```
The test suite includes a `kill -9` crash harness (derived tables must equal
a full oplog replay after any crash), oplog merge-law property tests, frozen
schema-version fixtures, and `EXPLAIN QUERY PLAN` pinning. Everything runs
offline.
## License
MIT OR Apache-2.0, at your option. See [NOTICE](NOTICE) for attributions
(Graphiti schema concepts, simple-graph traversal templates, Cortex scoring
ideas).