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

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 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 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:

// 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

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 (lines 639–648) provides optimized access:

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:

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 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 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 71–85, 1629 Core Wiki struct, write_page implementation, versioning logic
crates/ai-memory-store/src/ops.rs UpsertPage command, atomic flag transitions
crates/ai-memory-store/src/reader.rs 639–648, 760–770 Latest version queries, full history enumeration
crates/ai-memory-wiki/src/git.rs Git repository operations, commit generation
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).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →