DEV Community

Stanislav
Stanislav

Posted on

LedgerMind 3.0 3.3.2: How We Turned "It Works" into "It Works Brilliantly"

Spoiler: 497 commits, three sleepless nights with SQLite, and one very stubborn race condition that refused to die.

Reading time: ~12 minutes ยท For: AI agent developers, architecture drama enthusiasts


Introduction: We Had Three Versions, Now We Have... More

If you missed the last few months of LedgerMind's life, here's the short version: we took a system that in version 3.0 simply worked, and turned it into a system that works fast, reliably, and with elements of artificial intelligence.

Sounds like marketing bullshit? I get it. So let's jump straight to the facts:

Metric v3.0 v3.3.2 Change
Search (OPS) ~2,000 5,500+ +175%
Write (latency) ~500ms 14ms -97%
Commits between versions โ€” 497 ๐Ÿ˜…
Critical bugs in production Had them Zero now ๐ŸŽ‰

But let's start from the beginning. Because behind these numbers lies a real engineering drama.


Chapter 1: When Everything Broke (And We Fixed It)

The Tale of One Race Condition

We had a problem. A beautiful, classic TOCTOU race (Time-Of-Check-To-Time-Of-Use). Two agents simultaneously decide to write a decision for the same target. First checks โ€” no conflicts. Second checks โ€” no conflicts. First writes. Second writes. Boom. Metadata corrupted.

"This rarely happens," someone said.

"Rarely isn't never," replied CI/CD at 3 AM.

The fix: real ACID transactions with BEGIN IMMEDIATE, a global lock registry, and automatic stale lock cleanup after 10 minutes. Now you can run ten agents on one project โ€” they'll figure it out.

"Database is Locked": A Chronicle of Expected Death

SQLite is a wonderful thing until you try to write to it from a background worker and a user request simultaneously. Then it becomes... less wonderful.

sqlite3.OperationalError: database is locked
Enter fullscreen mode Exit fullscreen mode

This error haunted us like a ghost. We tried:

  • โŒ Increasing timeouts (didn't help)
  • โŒ Adding retry logic (helped, but hacky)
  • โŒ Praying to database gods (didn't work)

What worked: splitting enrichment batches into per-proposal transactions + worker.pid for detecting stuck workers + automatic stale lock cleanup.

Now the background worker calmly runs every 5 minutes, and users don't even notice it exists. As it should be.


Chapter 2: Features We Wanted Ourselves (And Built)

DecisionStream: Knowledge Has a Lifecycle Too

Before, knowledge in LedgerMind was static. You wrote it โ€” it sat there until you deleted it. Boring.

Now every piece of knowledge has three life phases:

PATTERN โ†’ EMERGENT โ†’ CANONICAL
Enter fullscreen mode Exit fullscreen mode
  1. PATTERN โ€” the system noticed a repeating event
  2. EMERGENT โ€” the pattern confirmed itself several times
  3. CANONICAL โ€” this is no longer just an observation, it's truth

LifecycleEngine manages transitions automatically. You do nothing โ€” the system decides when knowledge has "grown up."

Why? Because after a month of operation, you accumulate hundreds of decisions. And you want to see current ones in search, not those you wrote on day one and forgot.

Trajectory-Based Reflection: The System Learns to Think Like You

This is probably my favorite feature of v3.3.

Before: you record decisions, the system stores them.

After: the system analyzes sequences of your decisions and identifies thinking patterns.

# You just record decisions
memory.record_decision("Use PostgreSQL", target="db")
memory.record_decision("Add JSONB", target="db")
memory.record_decision("Migrations via Alembic", target="db")

# The system notices the pattern:
# "When user builds API โ†’ PostgreSQL + JSONB + Alembic"
# And next time will suggest this stack automatically
Enter fullscreen mode Exit fullscreen mode

This isn't magic. It's the Trajectory-based Reflection Engine, which builds graphs of your decisions and finds repeating paths in them.

Zero-Touch Automation: Fewer Clicks, More Code

We added Gemini CLI support and brought VS Code integration to "Hardcore" level:

Client Automation Level
VS Code Hardcore โ€” shadow context, terminal, chats
Claude Code Full โ€” auto-record + RAG
Cursor Full โ€” auto-record + RAG
Gemini CLI Full โ€” auto-record + RAG

What does this mean in practice? You don't think about LedgerMind at all. It just works. Before every LLM request, the system injects context from memory. After every response โ€” it writes the result automatically.

You work as usual. The system works for you.


Chapter 3: Optimizations, or How We Squeezed Out Milliseconds

Search: From 2,000 to 5,500+ OPS

Early in v3.3 development, we noticed something unpleasant: search slowed down. From ~4,000 OPS to ~2,000 OPS.

Cause: added linked_id validation for connections between events and decisions. Every search did a full table scan.

Fix: index on linked_id + fast-path heuristics for simple queries + metadata batching.

-- Before: slow JOIN without index
SELECT * FROM decisions WHERE linked_id IN (...)

-- After: fast lookup by index
CREATE INDEX idx_linked_id ON episodic_events(linked_id);
Enter fullscreen mode Exit fullscreen mode

Result: 5,500+ OPS for semantic search, 14,000+ OPS for keyword-only.

Write: 8 OPS with Full Git Audit

Writing a decision to LedgerMind isn't just INSERT INTO. It's:

  1. SQLite WAL write
  2. Git commit for cryptographic audit
  3. Vector embedding generation
  4. Link count updates

And all this fits into 8 operations per second. For comparison: v3.0 had ~2 OPS.

How? Deferred VectorStore loading, splitting transactions into proposals, path validation caching.

Mobile Version: 4-bit GGUF on Termux

Yes, LedgerMind now runs on Android via Termux. With a 4-bit quantized model.

Metric Mobile (GGUF) Server (MiniLM)
Search (latency) 0.13ms 0.05ms
Write (latency) 142.7ms 14.1ms
Search (OPS) 5,153 11,019

Why? Because sometimes you need to prototype on the go. And because we can.


Chapter 4: Bugs We Conquered (And How)

"At least 2 targets" โ€” The Error That Made No Sense

Symptom: when merging duplicates, the system returned at least 2 targets required, even when duplicates existed.

Cause: group size validation happened after transaction start, when data was already partially modified.

Fix: validate group size before transaction + randomize candidates to prevent infinite merge loops.

The Missing vitality Field

Symptom: CANONICAL knowledge ranks lower than fresh PATTERNs.

Cause: the vitality field needed for lifecycle ranking wasn't loaded in search fast-path.

Fix: add vitality calculation to fast-path + fix transitions in LifecycleEngine.

The Infinite Enrichment Loop

Symptom: worker processes the same proposals over and over. Tokens disappear. Time disappears.

Cause: SQL query didn't exclude already-processed records.

Fix: add enrichment_status field with pending โ†’ completed transition + stuck record detection.


Chapter 5: Refactoring Nobody Sees (But Everyone Feels)

Memory API Decomposition

Before: one huge Memory class at 2,000+ lines.

After: nine specialized services:

Memory (coordinator)
โ”œโ”€โ”€ EpisodicStore    # short-term events
โ”œโ”€โ”€ SemanticStore    # long-term decisions + Git
โ”œโ”€โ”€ VectorStore      # embeddings
โ”œโ”€โ”€ ConflictEngine   # conflict detection
โ”œโ”€โ”€ ResolutionEngine # supersede validation
โ”œโ”€โ”€ DecayEngine      # pruning old data
โ”œโ”€โ”€ ReflectionEngine # pattern discovery
โ””โ”€โ”€ LifecycleEngine  # phase management
Enter fullscreen mode Exit fullscreen mode

Why? Each component can be tested, optimized, and replaced independently. And when a new developer arrives in six months, they won't run away in horror.

Removing Legacy Settings

We removed:

  • preferred_language โ†’ now enrichment_language
  • arbitration_mode โ†’ replaced with intelligent conflict resolution
  • lite mode โ†’ completely cut from architecture

Why does this matter? Less dead code = fewer bugs = fewer questions like "what does this setting do?".


Epilogue: Should You Upgrade?

If you're on v3.0: Yes, immediately

Why:

  1. Performance: writes are 35x faster (500ms โ†’ 14ms)
  2. Reliability: race conditions and DB locks fixed
  3. Features: DecisionStream, Trajectory Reflection, Zero-Touch for Gemini
  4. Security: Bandit vulnerabilities patched
  5. Migration: automatic, non-destructive
# Backup
ledgermind-mcp run --path /path/to/v3.0/memory

# Upgrade
pip install --upgrade ledgermind

# Initialize
ledgermind init
Enter fullscreen mode Exit fullscreen mode

What's Next?

Judging by commits and TODOs in the code:

Feature Confidence Evidence
Real-time collaboration (CRDT) Medium Multi-agent namespacing groundwork
Cloud hosting Medium Docker + REST gateway ready
Knowledge graph visualization High DecisionStream ontology enables graph queries
LangChain/LlamaIndex integration High MCP protocol compatibility

Afterword: Personal Thoughts

When we started v3.3, I thought: "A few features, some optimizations, release in a month."

Reality: 497 commits, three critical bugs in production, one night debugging SQLite locking, and lots of coffee.

But when I see search running at 5,500+ OPS, the background worker doing its job without a single lock, the system automatically "understanding" patterns in my decisions โ€” I realize: it was worth it.

LedgerMind v3.3.2 isn't just "a new version." It's a system you can trust.

Now go build something awesome.


Article written based on analysis of 497 commits between v3.0.0 and v3.3.2. The author didn't sleep for two nights but will catch up tomorrow.

P.S. If you find a bug โ€” open an issue. We're fast. Promise.

P.P.S You can watch video tutorial on my X.com

Top comments (0)