# How Versioned Wiki Pages Are Managed in ai-memory: A Deep Dive

> Discover how ai-memory manages versioned wiki pages using immutable versioning, SQLite, and Git. Explore atomic operations and automatic commits for a complete history.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: deep-dive
- Published: 2026-08-28

---

**ai-memory uses an immutable versioning strategy that combines SQLite rows with git-tracked files, where each write creates a new version while preserving full history through atomic database operations and automatic git commits.**

Versioned wiki pages in ai-memory form the backbone of its knowledge management system. The `akitaonrails/ai-memory` repository implements a hybrid storage approach that treats the wiki as the single source of truth, ensuring no data loss while maintaining both programmatic queryability and human-readable file history.

## Architecture Overview: The Three-Layer Storage Model

The versioning system spans three interconnected layers:

- **SQLite store** — Tracks version metadata with `is_latest` flags
- **Filesystem** — Holds markdown files at `<data_dir>/wiki/<workspace_id>/<project_id>/<page-path>`
- **Git repository** — Records every write as a commit for external tooling

This design, found in [`crates/ai-memory-wiki/src/wiki.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/wiki.rs) lines 71–85 and 1629, guarantees durability and auditability without sacrificing query performance.

## How New Versions Are Created

### The Atomic Upsert Flow

When `Wiki::write_page` receives a `NewPage` command via `WriterHandle::UpsertPage`, it executes four atomic steps:

1. **Insert new row** — Creates a version record with `is_latest = 1`
2. **Invalidate previous version** — Updates the prior row to `is_latest = 0`
3. **Write filesystem** — Persists markdown to the wiki directory
4. **Commit to git** — Records the change through `GitAdapter`

This sequence in [`crates/ai-memory-wiki/src/wiki.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/wiki.rs) ensures that partial failures cannot leave the system in an inconsistent state. Either all four steps complete, or none do.

### Database Schema Design

The `pages` table uses a soft-delete pattern rather than hard deletion or update-in-place:

```rust
// Conceptual schema (from ops.rs UpsertPage implementation)
// Row structure: id, workspace_id, project_id, path, title, 
//                frontmatter, body, created_at, is_latest

```

Only one row per unique `(workspace_id, project_id, path)` combination carries `is_latest = 1`. Historical versions remain queryable with `is_latest = 0`, enabling time-travel reads without separate history tables.

### Code Example: Writing a Versioned Page

```rust
use ai_memory_wiki::{Wiki, NewPage, WriteContext};
use ai_memory_core::PagePath;

// Initialize wiki with git-backed storage
let wiki = Wiki::new(&data_dir, writer_handle.clone())?;

// This triggers the full versioning pipeline
wiki.write_page(
    NewPage {
        workspace_id: 1,
        project_id: 42,
        path: "architecture/decisions.md".into(),
        title: Some("API Gateway Decision".into()),
        frontmatter: serde_yaml::to_string(&meta)?,
        body: "## Context\nWe chose Kong over NGINX...".into(),

    },
    &WriteContext::default(),
)?;

```

After execution, the filesystem contains `<data_dir>/wiki/1/42/architecture/decisions.md` with a corresponding git commit, and the database holds both the new version (`is_latest = 1`) and any prior versions (`is_latest = 0`).

## Reading Versioned Content

### Latest Version Retrieval

`ReaderPool::read_page_latest` in [`crates/ai-memory-store/src/reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/reader.rs) (lines 639–648) provides optimized access:

```rust
use ai_memory_wiki::PagePath;

// Single query: SELECT ... WHERE is_latest = 1
let current = wiki.read_page(&PagePath::new("architecture/decisions.md"))?;
println!("Version {}: {}", current.version_id, current.title);

```

### Full Version History

For audit trails or rollback scenarios, `read_page_versions` exposes the complete chain without spawning new versions:

```rust
let history = wiki.read_page_versions(&PagePath::new("architecture/decisions.md"))?;

for version in history {
    println!(
        "v{} (latest={}) created at {}",
        version.id, version.is_latest, version.created_at
    );
}

```

This functionality, anchored in [`crates/ai-memory-store/src/reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/reader.rs) lines 760–770, powers re-indexing operations and historical analysis tools.

## Git Integration for External Tooling

The `GitAdapter` in [`crates/ai-memory-wiki/src/git.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/git.rs) bridges programmatic and human workflows. Every `write_page` generates:

- A git add of the modified markdown file
- A commit with metadata-derived message
- Optional push to remote (configurable)

This enables standard git tools—`git log`, `git diff`, GitHub interfaces—to inspect wiki history without database access.

## Key Source Files Reference

| File | Lines | Purpose |
|------|-------|---------|
| [`crates/ai-memory-wiki/src/wiki.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/wiki.rs) | 71–85, 1629 | Core `Wiki` struct, `write_page` implementation, versioning logic |
| [`crates/ai-memory-store/src/ops.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/ops.rs) | — | `UpsertPage` command, atomic flag transitions |
| [`crates/ai-memory-store/src/reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/reader.rs) | 639–648, 760–770 | Latest version queries, full history enumeration |
| [`crates/ai-memory-wiki/src/git.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/git.rs) | — | Git repository operations, commit generation |
| [`docs/wiki-migrations.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/wiki-migrations.md) | — | Schema evolution documentation |

## Summary

- **Immutable versions** — Every write creates a new row; updates only toggle `is_latest` flags
- **Atomic operations** — Database and filesystem changes complete together or roll back
- **Dual query paths** — Fast latest-version lookups via `is_latest = 1` index; full history via unfiltered queries
- **Git durability** — Automatic commits provide human-readable history and external tool compatibility
- **No data loss** — Superseded versions remain accessible for audit and recovery

## Frequently Asked Questions

### How does ai-memory prevent version conflicts during concurrent writes?

The `WriterHandle` serializes all `UpsertPage` commands through a single writer thread, eliminating race conditions. SQLite's transaction isolation ensures that `is_latest` flag updates are atomic even under concurrent read pressure.

### Can I restore a previous version of a wiki page?

Yes. Query the target version using `read_page_versions`, then call `write_page` with the historical content. This creates a *new* version with the restored content rather than mutating history, preserving the audit trail.

### What happens to git history when pages are deleted?

Deletion sets `is_latest = 0` for all versions of a page and removes the filesystem entry, but git retains the complete commit history. The database rows remain queryable through history APIs unless explicitly purged through separate maintenance operations.

### Does versioning impact query performance?

No. The `is_latest` column is indexed, making latest-version queries O(1). Historical queries scan only rows for the specific page path, not the full table, as enforced by composite indexes on `(workspace_id, project_id, path)`.