Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
- name: Test
run: cargo test --all-features

- name: Documentation
run: RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps

features:
name: Features (${{ matrix.features.name }})
runs-on: ubuntu-latest
Expand All @@ -61,10 +64,8 @@ jobs:
flags: --no-default-features --features tokio
- name: git-diff
flags: --no-default-features --features git-diff
- name: providers-http
flags: --no-default-features --features providers-http
- name: rpc
flags: --no-default-features --features rpc
- name: sync
flags: --no-default-features --features sync
- name: all features
flags: --all-features
steps:
Expand All @@ -80,5 +81,5 @@ jobs:
workspaces: .
key: features-${{ matrix.features.name }}

- name: Check
run: cargo check --all-targets ${{ matrix.features.flags }}
- name: Test
run: cargo test --all-targets ${{ matrix.features.flags }}
7 changes: 5 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@ jobs:
run: cargo fmt --all -- --check

- name: Run clippy
run: cargo clippy --all-targets -- -D warnings
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Run tests
run: cargo test
run: cargo test --all-features

- name: Build documentation
run: RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps

- name: Compute next version
id: version
Expand Down
13 changes: 2 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ exclude = [
".vscode/",
"benchmarks/",
"docs/",
"examples/",
"gitbooks/",
"paper/",
"requirements.txt",
Expand All @@ -35,20 +34,13 @@ tokio = ["dep:tokio"]
git-diff = ["dep:git2"]

# reqwest-based embedding / LLM HTTP providers (`memory::providers`). Pulls in
# the reqwest stack and needs an async runtime, so it implies `tokio`. The
# concrete providers land with goals C3/M3; this feature reserves the seam and
# gates the dependency.
# the reqwest stack and needs an async runtime, so it implies `tokio`.
providers-http = ["dep:reqwest", "tokio"]

# Live source synchronization (Composio HTTP pipelines and workspace scans).
# Host schedulers, credentials, RPC, and event buses remain outside the crate.
sync = ["dep:reqwest", "dep:tracing", "tokio"]

# serde schema / envelope surface for the RPC boundary (`memory::rpc`). Reserved
# for goal C5; gates the wire-facing surface without adding heavy dependencies
# (serde is already a core dependency).
rpc = []

# Persona distillation surface (`memory::persona`): ingests local coding-agent
# history, instruction files, and git commits into a durable persona memory
# layer (doc 06). Adds NO new dependencies — readers reuse `serde_json`,
Expand All @@ -57,7 +49,6 @@ rpc = []
# the OpenRouter reference provider, but the pipeline depends only on the
# `ChatProvider` / `Summariser` / `EmbeddingBackend` traits.
persona = []

[dependencies]
anyhow = "1"
log = "0.4"
Expand Down Expand Up @@ -88,7 +79,7 @@ walkdir = "2"
git2 = { version = "0.21", default-features = false, features = [
"vendored-libgit2",
], optional = true }
# reqwest pulls a large async HTTP stack — only for the `providers-http` feature.
# reqwest pulls a large async HTTP stack — only for live synchronization.
reqwest = { version = "0.12", default-features = false, features = [
"json",
"rustls-tls",
Expand Down
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

The human brain is a master at compression. It doesn't try to remember every passing detail; instead it aggressively prunes noise to keep a sharp, focused, easily accessible recall of what truly matters. Traditional AI memory systems do the opposite — they try to remember _everything_ and retrieve whatever is _similar_. But similar doesn't mean important. The result? Your AI drowns in stale, irrelevant context that degrades every response.

**TinyCortex** takes the brain's approach: it **intelligently forgets noise**. A multi-signal admission gate drops low-value content at ingest, and retrieval applies exponential time-decay so stale memories fade from recall while fresh, high-signal knowledge ranks first. The result is a memory engine that stays lean and focused instead of drowning in stale context.
**TinyCortex** takes the brain's approach: it **intelligently forgets noise**. A multi-signal admission gate drops low-value content at ingest. Retrieval provides semantic, keyword, graph, summary-tree, and freshness-scoring building blocks so hosts can choose an explicit ranking policy instead of treating every stored item as equally useful.

The hosted TinyCortex platform has been evaluated on [RAGAS](https://www.ragas.io/), TemporalBench, [BABILong](https://github.com/booydar/babilong/), and [Vending-Bench](https://andonlabs.com/evals/vending-bench-2) — see [Benchmarks](#-benchmarks) below for the reported results and what you can reproduce from this repo.

Expand All @@ -26,7 +26,7 @@ The hosted TinyCortex platform has been evaluated on [RAGAS](https://www.ragas.i

## Intelligent Noise Filtering

Every chunk passes a multi-signal admission gate at ingest low-value content is dropped before it ever pollutes the store — and retrieval ranking applies exponential time-decay (7-day half-life by default) so stale memories fade from recall. The store stays lean on its own — no manual cleanup.
Every chunk passes a multi-signal admission gate at ingest, so low-value content is dropped before it pollutes the store. The retrieval module exposes exponential freshness decay (7-day half-life by default) as a composable signal; built-in tree queries use semantic similarity or recency unless the host applies the hybrid composer.

![Interaction graph highlighting important knowledge](docs/images/gif/AppleEmailGraph.gif)

Expand All @@ -42,7 +42,7 @@ Markdown files are the source of truth. SQLite chunk rows, summary trees, vector

## Recency-Weighted Recall

Retrieval blends keyword relevance, vector similarity, graph proximity, and freshness into a single explainable score, so what comes back is a focused slice of long-term history rather than a noisy dump. Summary-tree hotness tracking promotes frequently written topics into their own trees. (The fully proactive "conscious recall" experience — surfacing memories without an explicit query — is part of the hosted TinyCortex platform, built on these primitives.)
TinyCortex exposes keyword relevance, vector similarity, graph proximity, freshness, and an explainable hybrid-score composer. These are policy primitives rather than a hidden global ranking rule: hosts can apply the supplied `WeightProfile`, while the built-in source/topic/global queries use their documented semantic or recency ordering. Summary-tree hotness tracking promotes frequently written topics into their own trees. (The fully proactive "conscious recall" experience — surfacing memories without an explicit query — is part of the hosted TinyCortex platform, built on these primitives.)

# ⚡ Getting Started

Expand All @@ -68,15 +68,23 @@ async fn main() -> anyhow::Result<()> {
.await?;

// Recall it with a keyword query.
let hits = store.search(MemoryQuery::text("theme preference")).await?;
let hits = store.search(MemoryQuery::text("dark mode")).await?;
for hit in hits {
println!("{:.3} {}", hit.score, hit.record.content);
}
Ok(())
}
```

The `InMemoryMemoryStore` is the simple reference backend. The full engine — content store, chunking, scoring, summary trees, vector/keyword/graph/hybrid retrieval, the diff ledger, and the async job queue — lives under the [`memory`](https://docs.rs/tinycortex/latest/tinycortex/memory/) module. See the **[documentation](https://tinyhumans.gitbook.io/tinycortex/)** for the architecture, concepts, and end-to-end ingest walkthroughs.
The `InMemoryMemoryStore` is the simple reference backend. The full engine — content store, chunking, scoring, summary trees, and vector/keyword/graph retrieval primitives — lives under the [`memory`](https://docs.rs/tinycortex/latest/tinycortex/memory/) module. Optional surfaces require Cargo features:

| Feature | Enables |
| --- | --- |
| `tokio` | Always-on queue worker and scheduler loops |
| `git-diff` | Git-backed snapshots, checkpoints, and read markers |
| `sync` | Composio and workspace synchronization pipelines |

See the **[documentation](https://tinyhumans.gitbook.io/tinycortex/)** for the architecture, concepts, and end-to-end ingest walkthroughs.

# 🧩 How It Works

Expand All @@ -96,12 +104,12 @@ source payload
| ----------------------------- | -------------------------------------------------------------------------------------------- |
| **Storage primitives** | Markdown content store, SQLite chunks, summary trees, vector DB, KV, entity index |
| **Ingest** | Canonicalize → chunk → score → embed → tree |
| **Retrieval** | Vector, keyword, graph, tree drill-down, and hybrid search with explainable score breakdowns |
| **Diff** | Git-backed source snapshots, checkpoints, and read-markers for change awareness |
| **Retrieval** | Vector, keyword, graph, tree drill-down, and composable hybrid-score primitives |
| **Diff** (`git-diff`) | Git-backed source snapshots, checkpoints, and read-markers for change awareness |
| **Entities & Graph** | Entity markdown files + a co-occurrence graph derived from the entity index |
| **Goals / Tool Memory** | Compact long-term goal list and durable tool-scoped rules |
| **Conversations / Archivist** | Transcript storage and conversion of turns into summary-tree leaves |
| **Queue** | Async jobs: extract, append, seal, flush-stale, re-embed, seal-document |
| **Queue** | Durable jobs; optional `tokio` feature adds always-on worker/scheduler loops |

Full details live in the **[documentation](https://tinyhumans.gitbook.io/tinycortex/)**.

Expand Down Expand Up @@ -138,7 +146,9 @@ See [`benchmarks/`](./benchmarks/README.md) for the full reported tables and for

# 🤝 Contributing

TinyCortex is built in Rust (2021 edition). Clone the repo and:
TinyCortex is built in Rust (2021 edition). Clone the repo, then run
`./scripts/setup.sh` once and `./scripts/test.sh` for the full local CI suite.
The underlying commands are:

```bash
cargo test # run unit + integration tests
Expand Down
55 changes: 53 additions & 2 deletions docs/spec/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Memory Engine Audit & Improvement Spec

_Audit date: 2026-07-11 · Baseline: `main` @ `c9d1afd` · All 1025 unit tests + 1 integration test green at time of audit._
_Initial audit: 2026-07-11 · Architecture follow-up: 2026-07-14 · Remediation implementation: 2026-07-14._

This folder holds the results of a full-codebase audit of the TinyCortex memory
engine and the improvement plan derived from it. The audit swept every
Expand All @@ -25,7 +25,58 @@ carries `file:line` evidence.
| [audit/09-verification-infrastructure.md](audit/09-verification-infrastructure.md) | Per-block verifiability: test coverage map, CI feature matrix, setup/test scripts |
| [audit/10-simplification-dead-weight.md](audit/10-simplification-dead-weight.md) | Duplication, dead/speculative code, dependency weight, error/async story |

## Executive summary
## Remediation status

The correctness remediation described by audits 01–06 is implemented. The
work preserves wire ids while closing the verified data-loss, concurrency,
parser, queue-settlement, retrieval, and contract defects. Fixes that were
already present were retained and covered rather than reimplemented.

The resulting trust baseline includes:

- atomic or compensated persistence at every audited crash boundary, including
document ingest, queue follow-ups, staged summaries, time-tree rebuilds,
goals, and source/tool-memory registries;
- concurrency-safe buffer sealing, conversation sequencing, source mutation,
read markers, and shared SQLite/entity-index ownership;
- SQL-bounded retrieval and graph operations without the audited 200/500/5000
silent truncation cliffs;
- fail-closed taint/category contracts, a real `Memory` implementation for the
reference store, validated partial config loading, and configurable scoring,
ingestion, retrieval-limit, queue, sync, and tree policy roots;
- a real ingest → durable queue drain → tree seal → retrieval functional test,
feature-matrix tests (including `sync`), setup/test scripts, corruption and
crash-window tests, and source files split below the 500-line repository cap;
- removal of the empty `rpc` and `providers-http` feature surfaces. Optional
features now correspond to concrete code rather than reserved placeholders.

Audits 07–10 intentionally also contain longer-horizon design alternatives,
such as replacing the shared transactional SQLite database with separately
owned persistence services or adding a remote store backend. Those are not
correctness defects and are not silently presented as completed here. The
shared database remains the documented atomicity boundary; the public
in-memory backend now implements the consolidated `Memory` contract, while
the separate [configurable-store specification](configurable-store.md) remains
the design for a future network backend.

Verification is recorded from clean commands run at the end of remediation;
the exact test and coverage totals below are updated only from command output.

| Gate | Final result |
| --- | --- |
| Formatting | `cargo fmt --all -- --check` passes |
| Static validation | all-feature check and clippy with warnings denied pass |
| Unit tests | 1300 passed |
| Functional tests | 15 passed; 1 credentialed live smoke intentionally ignored |
| Doctests | 4 passed; 1 example intentionally ignored |
| Documentation | strict all-feature rustdoc passes with no warnings |
| Line coverage | **90.60%** (`cargo llvm-cov --all-features --workspace`) |
| Packaging | `cargo package --no-verify` succeeds without warnings |

## Original audit executive summary

The following describes the pre-remediation baseline and is retained as the
rationale for the fixes, not as a statement about the current tree.

The engine is well-layered and richly documented, and the full test suite
passes — but the audit surfaced **4 critical** and **~20 major** verified
Expand Down
9 changes: 9 additions & 0 deletions docs/spec/improvement-plan.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Memory Engine Improvement Plan

> Remediation record (2026-07-14): phases 0, 1, 2, and 4 have been
> implemented with regression coverage. Phase 3's contract consolidation is
> complete for the local reference backend (`InMemoryMemoryStore` implements
> `Memory` and the conflicting store error was renamed); the network backend
> remains a separate future product capability described in
> [configurable-store.md](configurable-store.md), not an implemented feature.
> The architecture alternatives in audits 07–10 remain decision records where
> they propose replacing the shared transactional SQLite boundary.

Derived from the [audit findings](README.md). Phases are ordered by risk:
each phase is independently shippable, and within a phase the workstreams are
parallelizable (use separate worktrees per the repo guidelines). Finding IDs
Expand Down
14 changes: 14 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"

git submodule update --init --recursive

if command -v rustup >/dev/null 2>&1; then
rustup toolchain install stable --profile minimal --component rustfmt,clippy
fi

cargo fetch --locked
echo "TinyCortex development dependencies are ready."
15 changes: 15 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$repo_root"

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps

for feature in tokio git-diff sync; do
cargo test --all-targets --no-default-features --features "$feature"
done
cargo test --all-targets --no-default-features
9 changes: 3 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@
//! (`memory::queue::runtime`) instead of driving `run_once` by hand.
//! - `git-diff`: compiles in `memory::diff` (git-backed source snapshots,
//! diffs, checkpoints, read markers) and its native `git2`/libgit2 dependency.
//! - `providers-http`: compiles in `memory::providers` (reqwest-based
//! embedding / LLM HTTP providers). Implies `tokio`.
//! - `rpc`: compiles in `memory::rpc` (the serde wire-envelope surface for
//! exposing the engine over an RPC boundary).
//! - `sync`: compiles in the live Composio and workspace synchronization
//! pipelines and implies `tokio`.
//!
//! With every feature off, `cargo check` / `cargo test` still exercise the full
//! synchronous engine (storage, ingest, retrieval, tree, graph, goals, …); the
//! feature-gated modules only reserve a seam until their concrete
//! implementations land.
//! feature-gated modules contain concrete optional implementations.

pub mod memory;
Loading