# How the AI-Memory Wiki Handles Atomic Writes and Git Version Control

> Discover how the ai-memory wiki ensures crash-safe persistence and audit history using atomic writes and Git version control for every markdown page.

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

---

**The ai-memory wiki combines filesystem-level atomic writes via `write_atomic` with automatic Git versioning through `GitAdapter` to ensure crash-safe persistence and complete audit history for every markdown page.**

The akitaonrails/ai-memory project implements a durable wiki subsystem that treats every markdown file as a first-class persisted artifact. By integrating atomic file operations with embedded Git version control, the system guarantees data integrity during crashes while maintaining a queryable history of all changes. Understanding these mechanisms reveals how the wiki achieves production-grade reliability without external database dependencies.

## Atomic File Writes Implementation

The wiki's crash safety rests on a custom atomic write routine located in [`crates/ai-memory-wiki/src/atomic.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/atomic.rs). This module ensures that power failures or process crashes during save operations can never produce partially written or corrupted wiki pages.

### The write_atomic Function

The `write_atomic(path, bytes)` function implements a write-then-rename pattern that leverages filesystem atomicity guarantees. The implementation follows a strict sequence:

1. **Temporary file creation** – The function creates a temporary file in the same directory as the target using a `.ai-memory-tmp.*` prefix.
2. **Durable data persistence** – After writing all bytes to the temporary handle, the code invokes `fsync` (via `sync_data`) to force the data to disk.
3. **Atomic rename** – The temporary file is moved to the final destination using `tempfile::Builder::persist`, which performs an atomic rename operation that replaces the existing file instantly.
4. **Directory synchronization** – As a best-effort durability step, the parent directory is `fsync`-ed to ensure the directory entry is committed.

The function returns the inode (or file-index on Windows) of the resulting file, which downstream components use to distinguish self-generated writes from external modifications.

### Crash Safety and Watcher Coordination

Unit tests in the atomic module verify three critical guarantees: parent directories are created automatically, existing files are overwritten cleanly, and no stray temporary files remain after completion. The inode return value enables the filesystem watcher to ignore its own writes by comparing file identifiers, preventing infinite update loops while maintaining responsiveness to external changes.

## Git Version Control Integration

Version control logic resides in [`crates/ai-memory-wiki/src/git.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/git.rs) within the `GitAdapter` struct. This component provides lazy repository initialization, automatic committing, and historical data retrieval without requiring manual Git intervention.

### Repository Management with GitAdapter

The `GitAdapter::open_or_init(root)` method lazily initializes a Git repository at the wiki root if one does not exist, ensuring the wiki is always a valid Git repo. The `commit_all(message)` method stages and commits changes through the following workflow:

- **Comprehensive staging** – Invokes `index.add_all("*")` to stage all modifications in the working directory.
- **Fixed attribution** – Creates commits with the author identity `ai-memory <ai-memory@local>`.
- **Idempotent operation** – Returns `None` when the working tree is clean (no changes), otherwise returns the new commit OID as a string.

### Accessing Historical Data

Beyond writing history, the adapter exposes query capabilities for building revision-aware features. The `commit_count()` method returns the number of reachable commits, while `recent_checkpoints(limit)` retrieves summaries of the latest changes. For content restoration or diffing, `file_at_rev(rev, path)` reads blob content from any historical commit hash into a byte vector.

### Cross-Platform Reliability

The implementation includes platform-specific robustness measures. When libgit2 fails to open a newly created repository or execute commits—particularly on Windows or constrained environments—the code falls back to invoking the system `git` command directly. This dual-strategy ensures version control functionality survives library limitations while maintaining consistent API behavior across operating systems.

## Practical Implementation Examples

The following pattern demonstrates the coordinated use of atomic writes and Git versioning:

```rust
use std::path::Path;
use ai_memory_wiki::atomic::write_atomic;
use ai_memory_wiki::git::GitAdapter;

// 1️⃣ Write the markdown file safely.
let page_path = Path::new("/data/wiki/notes/example.md");
write_atomic(page_path, b"# Example\nContent goes here.")?;

// 2️⃣ Ensure the wiki repository exists.
let git = GitAdapter::open_or_init(Path::new("/data/wiki"))?;

// 3️⃣ Commit the change with a descriptive message.
if let Some(oid) = git.commit_all("Add example note")? {
    println!("Committed as {}", oid);
} else {
    println!("No changes to commit");
}

```

To retrieve historical content for comparison or restoration:

```rust
let rev = "a1b2c3d4";                 // commit hash
let path = Path::new("notes/example.md");
let old_content = git.file_at_rev(rev, path)?;
println!("At {} the file contained:\n{}", rev, String::from_utf8_lossy(&old_content));

```

## Summary

- **Atomic durability** – The `write_atomic` function in [`crates/ai-memory-wiki/src/atomic.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/atomic.rs) uses temporary files, explicit `fsync` calls, and atomic rename operations to eliminate partial write risks.
- **Self-aware writes** – Returning inode values from atomic writes allows the filesystem watcher to filter out its own modifications and avoid reaction loops.
- **Embedded versioning** – `GitAdapter` in [`crates/ai-memory-wiki/src/git.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-wiki/src/git.rs) provides transparent repository initialization, bulk staging, and commit creation with fallback to CLI Git commands.
- **Historical access** – Methods like `file_at_rev` enable reading any previous version of a wiki page directly from Git blob storage.
- **Coordinated workflow** – Higher-level components orchestrate atomic persistence followed by Git commits to create logical checkpoints that survive system crashes.

## Frequently Asked Questions

### How does the atomic write mechanism prevent data corruption during crashes?

The `write_atomic` function never modifies the target file directly. It writes to a temporary file, forces the data to disk with `fsync`, then performs an atomic rename to replace the original. If the process crashes before the rename completes, the original file remains untouched; if the crash occurs after the rename, the file contains the complete new content because the rename operation is atomic at the filesystem level.

### What happens if the Git commit fails in ai-memory?

The `GitAdapter` implements platform-specific fallbacks when libgit2 operations fail. On Windows or other systems where the library might fail to commit, the code automatically falls back to executing the system `git` command directly. This ensures that version control operations complete successfully even when the embedded library encounters platform-specific limitations.

### How does the filesystem watcher distinguish its own writes from user edits?

The `write_atomic` function returns the inode (or file-index on Windows) of the file after the atomic rename operation completes. The filesystem watcher compares this identifier against the files it observes in change events. When the inode matches a value recently returned by `write_atomic`, the watcher recognizes the change as self-generated and suppresses reaction to that event, preventing the system from re-processing its own outputs.

### Can I access old versions of wiki pages without using command-line Git?

Yes. The `GitAdapter` provides the `file_at_rev(rev, path)` method, which allows programmatic access to historical content using only the commit hash and file path. This returns the raw bytes of the file as it existed at that revision, enabling applications to build diff views, restoration features, or temporal queries without shelling out to the `git` command.