kronroe 0.3.1

Embedded temporal property graph database
Documentation
# Kronroe

[![CI](https://github.com/kronroe/kronroe/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/kronroe/kronroe/actions/workflows/ci.yml)
[![crates.io](https://img.shields.io/crates/v/kronroe.svg)](https://crates.io/crates/kronroe)
[![docs.rs](https://img.shields.io/docsrs/kronroe)](https://docs.rs/kronroe)
[![PyPI](https://img.shields.io/pypi/v/kronroe)](https://pypi.org/project/kronroe/)
[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](./LICENSE)
[![kronroe.dev](https://img.shields.io/badge/site-kronroe.dev-orange)](https://kronroe.dev)

**AI memory that never leaves the device.**
No server. No cloud. No data risk.

Kronroe is built for three audiences:

- **Privacy-regulated industries** — healthcare, education, legal, care homes.
  Patient notes, student records, and case files never leave the device.
  Bi-temporal storage means every fact has a full audit trail built in:
  "what did we know, and when did we know it?" is a first-class query.

- **Mobile and offline-first apps** — iOS and Android developers who need AI
  memory that works on a plane, in a hospital, in a care home with no wifi.
  Ships as a Swift Package and a Kotlin/JNI library. The same engine runs in
  WASM in-browser with zero network calls.

- **AI agent builders** — developers building agents that need to remember how
  their understanding of the world has changed over time. Drop-in replacement
  for Graphiti, mem0, and mcp-memory-service — without the Neo4j server,
  without the cloud API, without data leaving your infrastructure.

---

## What

Every existing embedded graph database treats time as your problem. You add `created_at` to your properties. You write `WHERE valid_at BETWEEN ...` queries. The database does not know that "Alice works at Acme" was true in 2023 and false in 2024.

Kronroe treats bi-temporal facts as a **type-level design primitive enforced by the storage engine**:

```rust
// Assert a temporal fact — valid time is part of the engine, not your schema
db.assert_fact("alice", "works_at", "Acme", Utc::now())?;

// Point-in-time query — first-class operation, not a WHERE clause trick
let employer = db.facts_at("alice", "works_at", past_date)?;

// Invalidation — old fact gets valid_to set; history is preserved, never deleted
db.invalidate_fact(&fact_id, Utc::now())?;

// Full-text search across all current facts
let results = db.search("where does Alice work", 10)?;

// Semantic vector search — pass pre-computed embeddings, temporal filtering included
db.assert_fact_with_embedding("alice", "bio", "Software engineer", Utc::now(), embedding)?;
let nearest = db.search_by_vector(query_vec, 5, None)?;
```

This is the DuckDB move. DuckDB did not "do SQLite better" — it said analytical queries deserve their own engine design. Kronroe says temporal knowledge evolution deserves its own graph engine design.

## Why now

Three use cases are completely unserved:

- **Privacy-regulated industries** — healthcare providers, schools, care
  homes, and legal tools want AI capabilities but cannot send sensitive
  data to the cloud. GDPR, HIPAA, and sector-specific regulations make
  cloud AI a compliance blocker. Kronroe runs entirely on-device —
  zero data egress, full audit trail by design.

- **AI agent memory** — agents that need to remember, update, and query
  facts about the world over time, without running a server. Kronroe
  replaces Graphiti + Neo4j, mem0, and mcp-memory-service with a single
  embedded library.

- **Mobile/edge** — iOS and Android apps that need AI memory without
  network latency, server infrastructure, or per-call API costs.
  The XCFramework and Kotlin/JNI library are under 6 MB and work offline.

The solutions developers reach for today (Graphiti + Neo4j, mcp-memory-service) require a running server, have no temporal model at the engine level, and do not run on mobile.

## Architecture

Pure Rust. No C dependencies. No network calls. Runs on every platform
where data privacy is non-negotiable.

| Layer | Crate | Notes |
|---|---|---|
| Storage engine | `crates/core/src/storage_append_log.rs` | Kronroe append-log backend |
| Full-text search | Kronroe lexical engine | BM25 + fuzzy matching (`feature: fulltext`) |
| Vector search | `crates/core/src/vector.rs` | Flat cosine similarity + temporal filtering (`feature: vector`) |
| Python bindings | `crates/python` | `PyO3` bindings for core + agent memory |
| MCP server | `crates/mcp-server` | stdio transport, 11 tools |
| iOS bindings | `crates/ios` | C FFI + XCFramework + Swift Package |
| Android bindings | `crates/android` | Hand-written JNI + Kotlin wrapper |
| WASM bindings | `crates/wasm` | In-memory backend only |

## Workspace

```
kronroe/
├── crates/
│   ├── core/           # kronroe — TemporalGraph engine, bi-temporal storage
│   ├── agent-memory/   # kronroe-agent-memory — high-level AgentMemory API
│   ├── mcp-server/     # kronroe-mcp — stdio MCP server binary
│   ├── python/         # kronroe-py — PyO3 bindings
│   ├── wasm/           # kronroe-wasm — WebAssembly bindings (in-memory)
│   ├── ios/            # kronroe-ios — C FFI staticlib + Swift Package
│   └── android/        # kronroe-android — JNI cdylib + Kotlin wrapper
├── python/
│   └── kronroe-mcp/    # pip shim — kronroe-mcp CLI entry point
└── docs/
```

## Quickstarts

### MCP server (Claude Desktop / any MCP client)

```bash
cargo install --path crates/mcp-server
```

Add to your MCP client config:

```json
{
  "mcpServers": {
    "kronroe": {
      "command": "kronroe-mcp",
      "env": { "KRONROE_MCP_DB_PATH": "~/.kronroe/memory.kronroe" }
    }
  }
}
```

The native `kronroe-mcp` binary is the supported MCP runtime. The server exposes
11 tools: `remember`, `recall`, `recall_scored`, `assemble_context`,
`facts_about`, `assert_fact`, `correct_fact`, `invalidate_fact`,
`what_changed`, `memory_health`, `recall_for_task`.

### Python

```python
from kronroe import KronroeDb, AgentMemory

db = KronroeDb.open("./memory.kronroe")
db.assert_fact("alice", "works_at", "Acme")
results = db.search("where does Alice work", 10)

memory = AgentMemory.open("./memory.kronroe")
facts = memory.facts_about("alice")
```

### Rust

```rust
use kronroe::{KronroeTimestamp, TemporalGraph, Value};

let db = TemporalGraph::open("./memory.kronroe")?;

let id = db.assert_fact("alice", "works_at", Value::Text("Acme".into()), KronroeTimestamp::now_utc())?;
let current = db.current_facts("alice", "works_at")?;
let historical = db.facts_at("alice", "works_at", past_date)?;
db.invalidate_fact(&id, KronroeTimestamp::now_utc())?;
```

## Capability Matrix

For stability guarantees and compatibility expectations across features/surfaces, see
[`docs/API-STABILITY-MATRIX.md`](./docs/API-STABILITY-MATRIX.md).

### Available (shipping in repo)

| Capability | Where | Quick verification |
|---|---|---|
| Bi-temporal fact model + core CRUD (`assert_fact`, `facts_at`, `invalidate_fact`, etc.) | `crates/core/src/temporal_graph.rs` | `cargo test -p kronroe` |
| Full-text search (BM25 + fuzzy) | `crates/core/src/temporal_graph.rs` (`feature: fulltext`, default on core) | `cargo test -p kronroe search_ --all-features` |
| Vector search with temporal filtering | `crates/core/src/temporal_graph.rs`, `crates/core/src/vector.rs` (`feature: vector`) | `cargo test -p kronroe vector_ --all-features` |
| Atomic fact + embedding write transaction | `assert_fact_with_embedding` in core | see vector durability/error tests in core suite |
| Idempotent writes (`assert_fact_idempotent`) | core + agent-memory wrappers | `cargo test -p kronroe idempotent --all-features` |
| `AgentMemory` API surface (`remember`, `recall`, `recall_scored`, `assemble_context`, confidence + source assertions) | `crates/agent-memory/src/agent_memory.rs` | `cargo test -p kronroe-agent-memory --all-features` |
| MCP server (11 tools) + Python shim | `crates/mcp-server`, `python/kronroe-mcp` | `cargo test -p kronroe-mcp` |
| Python bindings (`KronroeDb`, `AgentMemory`) | `crates/python/src/python_bindings.rs` | `cargo build -p kronroe-py` + `./crates/python/scripts/run_runtime_smoke.sh` |
| iOS package artifacts + behavior tests | `crates/ios` | `cargo test -p kronroe-ios` and `./crates/ios/scripts/run-swift-tests.sh` |
| WASM bindings (in-memory engine, no persistent file backend) | `crates/wasm/src/wasm_bindings.rs` | `cargo build -p kronroe-wasm` |
| Android JNI bindings + Kotlin wrapper | `crates/android/src/android_bindings.rs` | `cargo test -p kronroe-android` |
| WASM playground live deploy + smoke verification | `.github/workflows/deploy-site.yml`, `site/scripts/smoke-playground.mjs` | merge to `main` triggers deploy + smoke summary |

### Experimental (feature-gated, API may change)

| Capability | Gate | Current status |
|---|---|---|
| Hybrid retrieval API (`search_hybrid`) with two-stage reranking + score breakdown | `kronroe` features `hybrid-experimental` + `vector` | Implemented and tested in core; intentionally marked experimental |
| Agent-memory hybrid recall path (text + vector fusion) | `kronroe-agent-memory` feature `hybrid` | Implemented via core experimental API; contract may evolve |
| Contradiction detection (singleton predicates, Allen's interval overlap, conflict severity/policy) | `kronroe` feature `contradiction` | Engine-native, no LLM required; agent-memory auto-registers common singletons |
| Uncertainty model (age decay, source authority, effective confidence at query time) | `kronroe` feature `uncertainty` | Engine-native, pure Rust math; agent-memory auto-registers default volatilities |

### Planned (not shipping yet)

| Capability | Status |
|---|---|
| Rich NLP extraction/planning layer beyond current `AgentMemory` primitives | Planned |

## Contributing

Contributions are welcome. Before your first pull request is merged, you'll be asked to sign the [Contributor Licence Agreement](./CLA.md) — a bot will prompt you automatically. The CLA lets us maintain the dual-licence model while keeping the project open.

Naming standards for crate entrypoints and path references are documented in [`docs/NAMING-CONVENTIONS.md`](./docs/NAMING-CONVENTIONS.md).

## Licence

Kronroe is dual-licensed:

- **Open source**[GNU Affero General Public Licence v3.0]./LICENSE (AGPL-3.0) for open-source projects, personal use, and research
- **Commercial**[Commercial Licence]./LICENCE-COMMERCIAL.md for proprietary products and SaaS applications

If embedding Kronroe in a closed-source product, a commercial licence is required. See [LICENCE-COMMERCIAL.md](./LICENCE-COMMERCIAL.md) for details and how to get in touch.

Copyright © 2026 Kindly Roe Ltd