{"id":50337017,"url":"https://github.com/benoitpetit/mira","last_synced_at":"2026-05-29T14:01:34.824Z","repository":{"id":349977385,"uuid":"1204673248","full_name":"benoitpetit/mira","owner":"benoitpetit","description":"Long-term memory system for LLMs with optimal context budget allocation, approximation guarantees, and temporal coherence. 100% local, deterministic, O(n log n).","archived":false,"fork":false,"pushed_at":"2026-04-24T08:30:39.000Z","size":1464,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T10:33:10.228Z","etag":null,"topics":["context","llm","mcp","memory","opensource"],"latest_commit_sha":null,"homepage":"https://devbyben.fr","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benoitpetit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"liberapay":"devbyben/donate"}},"created_at":"2026-04-08T08:14:58.000Z","updated_at":"2026-04-24T08:28:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/benoitpetit/mira","commit_stats":null,"previous_names":["benoitpetit/mira"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/benoitpetit/mira","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fmira","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fmira/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fmira/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fmira/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benoitpetit","download_url":"https://codeload.github.com/benoitpetit/mira/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fmira/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33655441,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context","llm","mcp","memory","opensource"],"created_at":"2026-05-29T14:01:34.498Z","updated_at":"2026-05-29T14:01:34.807Z","avatar_url":"https://github.com/benoitpetit.png","language":"Go","funding_links":["https://liberapay.com/devbyben/donate"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./logo.png\" alt=\"MIRA Logo\" width=\"800\"\u003e\n\n  # MIRA\n  ### Memory with Information-theoretic Relevance Allocation\n\n  **Long-term Memory System for LLMs with Optimal Context Budget Allocation**\n\n  [![Go Version](https://img.shields.io/badge/Go-1.23+-00ADD8?style=flat-square\u0026logo=go)](https://golang.org/)\n  [![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE)\n  [![Version](https://img.shields.io/badge/Version-0.4.5-blue?style=flat-square)]()\n  [![Tests](https://img.shields.io/badge/Tests-~55%25-yellow?style=flat-square)]()\n\n  *100% Local • Deterministic (embedding variance \u003c 1e-6) • Clean Architecture*\n\n  [API Reference](docs/API_REFERENCES.md) • [Changelog](CHANGELOG.md) • [Skill](SKILL.md) • [Francais](README_FR.md) • [SOUL Extension](https://github.com/benoitpetit/soul)\n\n\u003c/div\u003e\n\n---\n\n## Table of Contents\n\n- [What is MIRA?](#what-is-mira)\n- [The Memory Revolution for LLMs](#the-memory-revolution-for-llms)\n- [How It Works](#how-it-works)\n- [3-Level Architecture (T0/T1/T2)](#3-level-architecture-t0t1t2)\n- [The CBA Algorithm](#the-cba-algorithm)\n- [Enhanced Recall Pipeline](#enhanced-recall-pipeline)\n- [Causal Graph](#causal-graph)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n- [MCP API](#mcp-api)\n- [Performance](#performance)\n- [Technical Architecture](#technical-architecture)\n- [Development](#development)\n- [Changelog](#changelog)\n\n---\n\n## What is MIRA?\n\n**MIRA** is a sophisticated long-term memory system designed specifically for **Large Language Models (LLMs)**. Unlike traditional memory systems that simply store and retrieve, MIRA uses **information-theoretic allocation** to optimize every token in the context window.\n\n### SOUL Extension: Identity Preservation\n\nMIRA answers *\"What does the agent know?\"* But a complete agent needs more: it needs to know *\"Who is it?\"*\n\n[**SOUL**](https://github.com/benoitpetit/soul) (System for Observed Unique Legacy) is an **optional identity extension** for MIRA that captures, stores, and recalls the personality, voice, and values of AI agents across sessions and model changes.\n\nTo embed SOUL in MIRA, start with `--with-soul` or set `soul.enabled: true` in config. When enabled, SOUL provides **8 additional MCP tools** (16 total) for:\n- Capturing identity from conversations\n- Recalling identity prompts for LLM context injection\n- Detecting identity drift after model changes\n- Generating reinforcement prompts after model swaps\n\nSOUL is **opt-in and disabled by default**. MIRA works perfectly alone (8 tools). To activate SOUL, use `--with-soul` flag or set `soul.enabled: true` in `config.yaml`. When enabled, they share the same SQLite database.\n\n| Configuration | Tools | What it answers |\n|---------------|-------|-----------------|\n| MIRA only | 8 `mira_*` | \"What does the agent know?\" |\n| MIRA + SOUL | 16 `mira_*` + `soul_*` | \"What does the agent know?\" + \"Who is the agent?\" |\n\n### The Problem MIRA Solves\n\nModern LLMs suffer from a fundamental problem: **the context window is limited** (4K-128K tokens), but conversations and projects span thousands of interactions. How do we decide what to keep in context?\n\n**Traditional approaches fail:**\n\n- [x] Simple RAG: Retrieval based only on similarity, ignores information density\n- [x] Sliding window: Loses critical information from the beginning\n- [x] Static summarization: Doesn't adapt to the current query\n- [x] Basic Vector DB: O(n) complexity, no budget management\n\n**MIRA provides the solution:**\n\n- [+] **Context Budget Allocation**: Optimizes every token across 6 dimensions\n- [+] **Information Density**: Prioritizes memory-rich facts\n- [+] **Temporal Coherence**: Maintains narrative continuity\n- [+] **Causal Graph**: Understands cause-effect relationships\n- [+] **O(log n) Search**: HNSW for millions of memories\n- [+] **Clean Architecture**: Maintainable, testable, extensible\n\n---\n\n## The Memory Revolution for LLMs\n\n### What MIRA Brings New\n\n#### 1. **Information Allocation (CBA)**\n\nInstead of simply retrieving the \"most similar\", MIRA solves an **optimization problem under constraint**: maximize useful information within a fixed token budget.\n\n```\nScore(m) = Relevance × Density × Recency × (1-Overlap) × Coherence × CausalPenalty\n```\n\n#### 2. **Triple Representation (T0/T1/T2)**\n\nEach memory exists in 3 forms for different uses:\n\n- **T0 (Verbatim)**: Full original text\n- **T1 (Fingerprint)**: Structured extracted facts (~15% of tokens)\n- **T2 (Embedding)**: 384D semantic vector for search\n\n#### 3. **Integrated Causal Graph**\n\nAutomatic detection of relations (BECAUSE, TRIGGERED, CONTRADICTS, UPDATES, RESOLVES) to trace reasoning chains.\n\n#### 4. **Adaptive Rendering**\n\nBased on remaining budget, MIRA intelligently chooses the detail level:\n\n- **Header** (5 tokens): Reference only\n- **Fingerprint** (~15% tokens): Essential facts\n- **Verbatim** (100% tokens): Full text\n\n---\n\n## How It Works\n\n### Overview Flow\n\n```\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         MEMORY STORAGE                                  │\n├─────────────────────────────────────────────────────────────────────────┤\n│                                                                         │\n│   Input Text         T1,T2 Extraction        Atomic Storage             │\n│   ┌─────────┐       ┌──────────────┐          ┌─────────────────┐       │\n│   │\"We      │──────→│  Fingerprint │─────────→│  SQLite + HNSW  │       │\n│   │ decided │       │  + Embedding │          │  (WAL Mode)     │       │\n│   │ to use  │       └──────────────┘          └─────────────────┘       │\n│   │PostgreSQL\"            │                       │                     │\n│   └─────────┘             ↓                       ↓                     │\n│                        T1: {                 Vector Index               │\n│                          - decision: \"PostgreSQL\"  ℝ³⁸⁴                 │\n│                          - rejected: [\"MySQL\",     HNSW O(log n)        │\n│                                      \"MongoDB\"]                         │\n│                          - reason: [\"ACID\", \"Exp\"]                      │\n│                          - type: DECISION                               │\n│                                                                         │\n│                         T2: [0.23, -0.15, 0.89, ...] 384D               │\n│                                                                         │\n└─────────────────────────────────────────────────────────────────────────┘\n\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         RETRIEVAL (RECALL)                              │\n├─────────────────────────────────────────────────────────────────────────┤\n│                                                                         │\n│   Query \"Why PostgreSQL?\"                                               │\n│       │                                                                 │\n│       ▼                                                                 │\n│   ┌─────────────┐    ┌─────────────────┐    ┌──────────────────────┐    │\n│   │ Embedding   │───→│  HNSW Search    │───→│  Composite Scoring   │    │\n│   │ Query       │    │  Top 100        │    │  CBA Algorithm       │    │\n│   │ ℝ³⁸⁴        │    │  O(log n)       │    │  O(n log n)          │    │\n│   └─────────────┘    └─────────────────┘    └──────────────────────┘    │\n│                                                        │                │\n│                                                        ▼                │\n│                                              Greedy Selection           │\n│                                              with 4000 token budget     │\n│                                                        │                │\n│       ┌────────────────────────────────────────────────┘                │\n│       ▼                                                                 │\n│   Optimized Result:                                                     │\n│   ┌───────────────────────────────────────────────────────────────┐     │\n│   │ [1] Fingerprint: \"PostgreSQL Decision (ACID, expertise)\" 45tk │     │\n│   │ [2] Verbatim: \"Meeting 04/15 - DB discussion...\"         120tk│     │\n│   │ [3] Header: \"Sprint 5 deadline\"                           5tk │     │\n│   │ ...                                                           │     │\n│   │ Total: 3987/4000 tokens (99.7% utilization)                   │     │\n│   └───────────────────────────────────────────────────────────────┘     │\n│                                                                         │\n└─────────────────────────────────────────────────────────────────────────┘\n```\n\n### The CBA Composite Score\n\nFor each candidate memory, MIRA calculates a **multidimensional score**:\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                     CBA SCORE FORMULA                               │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│   S(m) = ρ × δ × η × (1-σ) × τ × χ × 𝟙[ρ\u003eθ]                         │\n│                                                                     │\n│   where:                                                            │\n│   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━    │\n│   ρ (rho)    = Semantic Relevance      cos(embedding_m, embedding_q)│\n│   δ (delta)  = Information Density     sigmoid(facts/√tokens)       │\n│   η (eta)    = Temporal Weight         exp(-λ × age)                │\n│   σ (sigma)  = Max Overlap             sim(m, already_selected)     │\n│   τ (tau)    = Session Boost           +20% if same session         │\n│   χ (chi)    = Causal Penalty          avoids long chains           │\n│   𝟙[ρ\u003eθ]     = Relevance Threshold     eliminates if ρ \u003c 0.6        │\n│                                                                     │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 3-Level Architecture (T0/T1/T2)\n\n### Why 3 Levels?\n\nThe human brain doesn't record everything with the same fidelity. MIRA mimics this hierarchy:\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                        T0/T1/T2 HIERARCHY                           │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│   LEVEL T0 - VERBATIM (Episodic Memory)                             │\n│   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━   │\n│   \"Meeting April 15, 2024 at 14:30.                                 │\n│    Participants: Marie (Tech Lead), Jean (DevOps), Sophie (PO)      │\n│    Marie: 'I propose we migrate to PostgreSQL for v2'               │\n│    Jean: 'It requires training, but it's more robust'               │\n│    Sophie: 'Client approves for Sprint 5'                           │\n│    Final decision: PostgreSQL migration approved\"                   │\n│                                                                     │\n│    • Storage: Full UTF-8 text (max 64KB)                            │\n│    • Usage: Rich context when budget allows                         │\n│    • Cost: ~200 tokens                                              │\n│                                                                     │\n│                              ↓ NLP Extraction                       │\n│                                                                     │\n│   LEVEL T1 - FINGERPRINT (Semantic Memory)                          │\n│   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━   │\n│   {                                                                 │\n│     \"type\": \"decision\",                                             │\n│     \"decision\": \"PostgreSQL Migration\",                             │\n│     \"rejected\": [\"MySQL\", \"MongoDB\"],                               │\n│     \"reason\": [\"ACID Robustness\", \"Client validation\"],             │\n│     \"assignee\": \"Jean\",                                             │\n│     \"deadline\": \"Sprint 5\",                                         │\n│     \"validated_by\": \"Sophie (PO)\"                                   │\n│   }                                                                 │\n│                                                                     │\n│    • Storage: Structured canonical JSON                             │\n│    • Usage: Dense context when budget is medium                     │\n│    • Cost: ~30 tokens (15% of T0)                                   │\n│                                                                     │\n│                              ↓ Embedding                            │\n│                                                                     │\n│   LEVEL T2 - EMBEDDING (Procedural Memory)                          │\n│   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━   │\n│   [0.23, -0.15, 0.89, -0.42, 0.67, ...]  // 384 dimensions          │\n│                                                                     │\n│    • Storage: float32[384] vector                                   │\n│    • Usage: O(log n) vector search                                  │\n│    • Cost: 0 tokens (search only)                                   │\n│                                                                     │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### Memory Types and Decay\n\n| Type           | λ (day⁻¹) | Half-life | Auto-Archive | Usage                   |\n| -------------- | --------- | --------- | ------------ | ----------------------- |\n| `decision`     | 0.001     | ~693 days | No           | Architectural decisions  |\n| `fact`         | 0.005     | ~139 days | No           | Knowledge, facts         |\n| `preference`   | 0.01      | ~69 days  | No           | User preferences         |\n| `session_note` | 0.1       | ~7 days   | 30 days      | Session notes           |\n| `debug_log`    | 0.5       | ~1.4 days | 7 days       | Debug logs              |\n\n---\n\n## The CBA Algorithm\n\n### Context Budget Allocator v2\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                    CBA ALGORITHM - O(n²)                            │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│  INPUT:  Query q, Budget B (tokens), Wing w, Room r                 │\n│  OUTPUT: List of memories with render mode                          │\n│                                                                     │\n│  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━   │\n│                                                                     │\n│  1. EMBEDDING                                                       │\n│     e_q ← Embed(q) with LRU cache (1000 entries)                    │\n│                                                                     │\n│  2. VECTOR SEARCH                                                   │\n│     C ← HNSW_Search(e_q, N=100, w, r)        # O(log n)             │\n│     If HNSW not ready: C ← SQLite_Search(e_q, N=100)  # Fallback    │\n│                                                                     │\n│  3. EARLY PRUNING                                                   │\n│     C' ← {c ∈ C : ρ(c,q) \u003e 0.6}                                     │\n│     If C' = ∅: C' ← top-5(C) by ρ                                  │\n│                                                                     │\n│  4. INITIAL SCORING                                                 │\n│     For each c ∈ C':                                                │\n│        c.score ← ρ(c) × δ_sigmoid(c) × η_recency(c)                 │\n│                                                                     │\n│  5. GREEDY SELECTION WITH DYNAMIC RENORMALIZATION                   │\n│     S ← ∅, tokens_used ← 0                                         │\n│     PQ ← MaxHeap(C')  # by initial score                            │\n│                                                                     │\n│     WHILE PQ ≠ ∅ AND tokens_used \u003c B:                              │\n│        c ← Pop(PQ)                                                  │\n│                                                                     │\n│        # Dynamic recalculation (depends on already selected S)      │\n│        c.σ_max ← max_{s∈S} similarity(c,s)                          │\n│        c.χ ← exp(-0.15 × |causal_links(c,S)|)                       │\n│        c.τ ← 1.2 if |time(c) - time(S)| \u003c 2h else 1.0               │\n│                                                                     │\n│        adjusted_score ← c.score × (1-c.σ_max) × c.χ × c.τ           │\n│                                                                     │\n│        # Check if next has better score                             │\n│        If PQ[0].score × 0.8 \u003e adjusted_score:                       │\n│           Push(PQ, c) with adjusted_score                           │\n│           continue                                                  │\n│                                                                     │\n│        # Determine mode based on REMAINING BUDGET                   │\n│        remaining ← B - tokens_used                                  │\n│        mode ← ChooseMode(c, remaining)                              │\n│        cost ← CalculateCost(c, mode)                                │\n│                                                                     │\n│        # Downgrade if necessary                                     │\n│        If tokens_used + cost \u003e B:                                   │\n│           mode ← Downgrade(mode)  # Verbatim → Fingerprint → Header │\n│           cost ← Recalculate(mode)                                  │\n│           If tokens_used + cost \u003e B: continue                       │\n│                                                                     │\n│        S ← S ∪ {c}, tokens_used ← tokens_used + cost                │\n│                                                                     │\n│  6. RETURN S sorted by descending score                             │\n│                                                                     │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### Adaptive Render Modes\n\n| Remaining Budget | Mode        | Tokens | Content              |\n| ---------------- | ----------- | ------ | -------------------- |\n| \u003c 100            | Header      | 2-5    | `[type\\|date\\|wing]` |\n| \u003c 1000           | Fingerprint | ~15%   | Essential facts T1   |\n| ≥ 1000           | Verbatim    | 100%   | Original text T0     |\n\n---\n\n## Enhanced Recall Pipeline\n\nMIRA's recall uses a **multi-stage retrieval pipeline** that goes far beyond simple vector similarity:\n\n```\nQuery → Expansion → Dense (HNSW) + Lexical (FTS5) → RRF Fusion → Clustering → Tag Boost → Adaptive Threshold → CBA Greedy Selection\n```\n\n### 1. Query Expansion\nBefore embedding, MIRA generates semantically-close variants of the query (cleaned, without stop-words, top keywords) and **averages their embeddings**. This improves cross-lingual retrieval and robustness against vocabulary mismatch.\n\n### 2. Hybrid Search (Dense + Lexical)\n- **Dense**: HNSW O(log n) vector search\n- **Lexical**: SQLite FTS5 full-text search (auto-enabled if available)\n- **Fusion**: Reciprocal Rank Fusion (`k=60`) merges both rankings into a single candidate list\n\n### 3. Search-Time Clustering\nCandidates are grouped by cosine similarity ≥ 0.88. Near-duplicates are collapsed, and only the best representative per cluster proceeds to scoring. This prevents budget waste on redundant memories.\n\n### 4. Tag-Based Retrieval\nA new `memory_tags` table indexes extracted entities, subjects, and keywords. Candidates matching query tags receive a small additive relevance boost.\n\n### 5. Adaptive Threshold Methods\nInstead of a fixed 0.6 relevance floor, MIRA now supports three dynamic methods:\n\n| Method | Description | Default |\n|--------|-------------|---------|\n| `iqr` | First quartile of score distribution | Yes |\n| `elbow` | Largest derivative drop (elbow method) | |\n| `mean_stddev` | mean - stddev | |\n\nThe threshold is clamped between `0.15` (floor) and `0.75` (ceiling).\n\n### 6. Heuristic Reranker (Optional)\nA lightweight pure-Go reranker scores top-k candidates using:\n- Jaccard-like token overlap\n- Exact phrase presence bonus\n- Length balance preference\n\nBlended with semantic relevance: `0.7*semantic + 0.3*rerank`.\n\n### 7. Fallback Vector Store\nIf HNSW is not yet ready (e.g., building from scratch), a transparent fallback wrapper automatically routes searches to the SQLite vector store. Recall never fails.\n\n---\n\n## Causal Graph\n\n### Supported Relations\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                      CAUSAL RELATIONS                               │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│   BECAUSE                    A ←────────── B                        │\n│   \"B explains why A\"         Bug understood  Because we analyzed    │\n│                              ───────────→   the logs                │\n│                                                                     │\n│   TRIGGERED                  A ←────────── B                        │\n│   \"B triggered A\"            Migration    After the decision        │\n│                              ───────────→  meeting                  │\n│                                                                     │\n│   CONTRADICTS                A ←────────→ B                         │\n│   \"A and B contradict\"       Option A     Option B                  │\n│                              ───────────→  incompatible             │\n│                                                                     │\n│   UPDATES                    A ←────────── B                        │\n│   \"B replaces/updates A\"     Spec v1      Spec v2                   │\n│                              ───────────→  (new version)            │\n│                                                                     │\n│   RESOLVES                   A ←────────── B                        │\n│   \"B resolves problem A\"     Bug #123     Fix #124                  │\n│                              ───────────→  (correction)             │\n│                                                                     │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### Automatic Detection\n\nRelations are automatically detected via linguistic patterns:\n\n```go\ncausalPatterns := map[RelationType]*regexp.Regexp{\n    RelTriggered:   regexp.MustCompile(`(?i)(?:following|after|in response to)`),\n    RelBecause:     regexp.MustCompile(`(?i)(?:because|since|due to|in reason of)`),\n    RelContradicts: regexp.MustCompile(`(?i)(?:contradicts|in contradiction|however)`),\n    RelUpdates:     regexp.MustCompile(`(?i)(?:updates|replaces)`),\n    RelResolves:    regexp.MustCompile(`(?i)(?:resolves|solves|fixes)`),\n}\n```\n\n---\n\n## Installation\n\n### Prerequisites\n\n- Go 1.23+ (if building from source)\n- SQLite3 (included)\n- ~100MB disk space for embedding model\n\n### From Sources\n\n```bash\n# Clone the repository\ngit clone https://github.com/benoitpetit/mira.git\ncd mira\n\n# Build\ngo build -o mira ./cmd/mira\n\n# Verify\n./mira --version\n```\n\n### Via Go Install\n\n```bash\ngo install github.com/benoitpetit/mira/cmd/mira@latest\n```\n\n### Binary Releases\n\nDownload pre-compiled binaries from the [Releases](https://github.com/benoitpetit/mira/releases) page:\n\n```bash\n# Linux/macOS\ntar -xzf mira-linux-amd64.tar.gz\nsudo mv mira /usr/local/bin/\nmira --version\n\n# Windows\nunzip mira-windows-amd64.zip\n.\\mira.exe --version\n```\n\n---\n\n## Quick Start\n\n### 1. Initialization\n\n```bash\n# Copy example configuration\ncp config.example.yaml config.yaml\n\n# Edit to your needs\nnano config.yaml\n```\n\n### 2. Start the MCP Server\n\n```bash\n# stdio mode (for Claude Desktop, Cursor, etc.)\n./mira\n\n# With custom config file\n./mira -config ./config.yaml\n\n# Run database migrations only\n./mira -migrate\n```\n\n### 3. Use MCP Tools\n\n#### Store a Memory\n\n```json\n{\n  \"tool\": \"mira_store\",\n  \"arguments\": {\n    \"content\": \"We decided to migrate to PostgreSQL for v2. Rejected: MySQL (not ACID), MongoDB (not relational). Reason: ACID and team expertise. Approved by CTO. Assigned to Jean.\",\n    \"wing\": \"backend-team\",\n    \"room\": \"database-migration\"\n  }\n}\n```\n\n#### Retrieve Context\n\n```json\n{\n  \"tool\": \"mira_recall\",\n  \"arguments\": {\n    \"query\": \"Why did we choose PostgreSQL?\",\n    \"budget\": 2000,\n    \"wing\": \"backend-team\"\n  }\n}\n```\n\n**Response:**\n\n```\n=== MIRA CONTEXT ===\nQuery: Why did we choose PostgreSQL? | Budget: 2000\nWing: backend-team\n\n--- [1] FINGERPRINT (45 tokens) ---\nDecision: PostgreSQL Migration\nRejected: MySQL, MongoDB\nReason: ACID, team expertise\nApproved by: CTO\nAssigned: Jean\n\n--- [2] VERBATIM (120 tokens) ---\nWe decided to migrate to PostgreSQL for v2...\n[full content]\n\n=== Total: 165/2000 tokens (8.3%) ===\n```\n\n#### Causal Chain\n\n```json\n{\n  \"tool\": \"mira_causal_chain\",\n  \"arguments\": {\n    \"id\": \"uuid-of-the-decision\",\n    \"max_depth\": 3,\n    \"include_consequences\": true\n  }\n}\n```\n\n---\n\n## Configuration\n\n### config.yaml File\n\n```yaml\nsystem:\n  version: \"0.4.7\"\n\nstorage:\n  path: \".mira\"\n  sqlite:\n    journal_mode: WAL\n    synchronous: NORMAL\n    cache_size: -64000\n    mmap_size: 268435456\n    temp_store: MEMORY\n\nembeddings:\n  current_model: \"sentence-transformers/all-MiniLM-L6-v2\"\n  model_hash: \"a2d8f3e9\"\n  dimension: 384\n  batch_size: 32\n  cache_size: 1000\n\n# HNSW Vector Index Configuration\nhnsw:\n  M: 32 # Max neighbors per node (tuned for better recall, see v0.4.2)\n  Ml: 0.25 # Level generation factor\n  ef_construction: 0 # Inactive — not supported by underlying hnsw library\n  ef_search: 100 # Dynamic candidate list for search (tuned, see v0.4.2)\n\nallocator:\n  default_budget: 4000\n  max_candidates: 100\n  early_pruning_threshold: 0.6\n  session_window_seconds: 7200\n  session_boost_beta: 0.2\n  session_boost_max: 1.2\n  causal_penalty_alpha: 0.15\n  density_sigmoid:\n    k: 2.0\n    mu: 0.3\n\ndecay_rates:\n  decision: 0.001\n  fact: 0.005\n  preference: 0.01\n  session_note: 0.1\n  debug_log: 0.5\n\narchive_thresholds:\n  session_note: 30\n  debug_log: 7\n\noverlap_cache:\n  ttl_days: 30\n  max_entries: 1000000\n\nextraction:\n  min_entity_length: 2\n  causal_lookback: 50\n  causal_max_days: 30\n\n# Enhanced recall configuration\nrecall:\n  adaptive_threshold_method: \"iqr\"\n  adaptive_threshold_floor: 0.15\n  adaptive_threshold_ceiling: 0.75\n  enable_fts5: true\n  fts5_limit: 100\n  rrf_k: 60\n  query_expansion:\n    enabled: true\n    num_variants: 3\n    temperature: 0.3\n  search_time_clustering:\n    enabled: true\n    similarity_threshold: 0.88\n  reranker:\n    enabled: false\n    top_k: 30\n\n# SOUL identity extension (disabled by default)\nsoul:\n  enabled: false\n\nmcp:\n  name: \"mira\"\n  version: \"0.4.7\"\n  transport: \"stdio\"  # stdio is the only supported transport\n  timeout_seconds: 30\n\n# Prometheus metrics export\nmetrics:\n  enabled: true\n  prometheus_addr: \":9090\"\n  report_interval_seconds: 60\n\n# Webhook notifications\nwebhooks:\n  enabled: false\n  workers: 3\n  queue_size: 1000\n  timeout_seconds: 30\n  endpoints: []\n```\n\n---\n\n## MCP API\n\n### Available Tools\n\n| Tool                | Description                           |\n| ------------------- | ------------------------------------- |\n| `mira_store`        | Store memory with T0→T1,T2 extraction |\n| `mira_recall`       | Retrieve optimal context with budget  |\n| `mira_load`         | Load full verbatim by ID              |\n| `mira_causal_chain` | Trace causal chain                    |\n| `mira_status`       | System statistics and health          |\n| `mira_timeline`     | Filtered chronological reconstruction |\n| `mira_archive`      | Archive and clean old memories        |\n| `mira_clear_memory` | Permanently delete all or room-scoped memories |\n\n### Fallback Wings\n\nWhen recalling from a specific wing yields no results, `mira_recall` supports comma-separated fallback wings:\n\n```json\n{\n  \"tool\": \"mira_recall\",\n  \"arguments\": {\n    \"query\": \"database migration strategy\",\n    \"budget\": 2000,\n    \"wing\": \"backend-team\",\n    \"fallback_wings\": \"platform-team,dba-team\"\n  }\n}\n```\n\nIf the primary wing has no matching memories, MIRA will automatically search the fallback wings in order.\n\n### Multilingual \u0026 Broad Search\n\n`mira_recall` supports queries in any language (English, French, Spanish, Italian, German, etc.) thanks to cross-lingual embeddings. If the initial semantic search yields sparse results — for example, when a query in one language searches against memories stored in another — MIRA automatically broadens the search with relaxed thresholds and merges the results. You do not need to translate queries or adjust parameters.\n\n```json\n{\n  \"tool\": \"mira_recall\",\n  \"arguments\": {\n    \"query\": \"règles de langue français anglais\",\n    \"budget\": 2000,\n    \"wing\": \"general\"\n  }\n}\n```\n\nSee [API_REFERENCES.md](docs/API_REFERENCES.md) for detailed API reference and usage examples.\n\n### Health Check Endpoints\n\nWhen metrics are enabled, MIRA exposes health endpoints:\n\n```bash\n# Full health check (includes DB, Vector Store, Embedder)\ncurl http://localhost:9090/health\n\n# Liveness probe (Kubernetes)\ncurl http://localhost:9090/health/live\n\n# Readiness probe (Kubernetes)\ncurl http://localhost:9090/health/ready\n\n# Prometheus metrics\ncurl http://localhost:9090/metrics\n```\n\n---\n\n## Performance\n\n### Algorithmic Complexities\n\n| Operation        | Complexity | Notes            |\n| ---------------- | ---------- | ---------------- |\n| Store T0,T1,T2   | O(1)       | Atomic insertion |\n| Vector Search    | O(log n)   | HNSW ANN         |\n| CBA Scoring      | O(n)       | n = candidates   |\n| Allocation       | O(n²)      | Greedy selection |\n| Causal Graph BFS | O(V+E)     | V=nodes, E=edges |\n\n### Real-World Performance\n\n| Metric            | Value                 |\n| ----------------- | --------------------- |\n| HNSW Search       | ~0.14 ms for 10K vectors (benchmarked, O(log n)) |\n| SQLite Search     | ~50 ms for 10K vectors (estimated) |\n| Full Allocation   | ~35 ms for 100 candidates (estimated) |\n| Cosine Similarity | ~3.3M ops/sec         |\n\n### Optimizations in v0.3.3\n\n- **Query Expansion**: Multi-variant embedding averaging for robust cross-lingual retrieval\n- **FTS5 Lexical Search**: SQLite full-text search integrated with auto-triggers and backfill\n- **RRF Hybrid Fusion**: Reciprocal Rank Fusion (`k=60`) combining dense HNSW and lexical FTS5 results\n- **Search-Time Clustering**: Real-time deduplication with cosine-similarity clustering (threshold 0.88)\n- **Tag-Based Retrieval**: `memory_tags` table with automatic tag boosting in CBA scoring\n- **Heuristic Reranker**: Optional lightweight lexical reranker for precision improvement\n- **Adaptive Threshold Methods**: Dynamic relevance pruning with `iqr`, `elbow`, and `mean_stddev` strategies\n- **Fallback Vector Store**: Transparent HNSW → SQLite fallback when the index is not ready\n- **Clear Memory Tool**: New `mira_clear_memory` MCP tool for global or room-scoped memory deletion\n- **Causal Chain T0 Resolution**: `mira_causal_chain` now correctly resolves `T0:` verbatim references to fingerprint IDs\n- **ID Visibility in Outputs**: `mira_recall` and `mira_timeline` now include memory IDs for downstream tool chaining\n- **LLM-Self-Correction Errors**: Invalid ID errors are now actionable, telling LLMs exactly where to get valid IDs\n\n### Optimizations in v0.3.1\n\n- **Lazy Evaluation**: Overlap calculation only for promising candidates\n- **LRU Cache**: 1000 entries for query embeddings\n- **HNSW Persistence**: Fast index reload on restart\n- **SQLite WAL Mode**: Concurrent read/write performance\n- **Adaptive Threshold**: Lowered relevance threshold for small corpora (\u003c10 memories)\n- **Default Room Mapping**: Auto-assigns standard rooms based on memory type\n\n---\n\n## Technical Architecture\n\n### Clean Architecture (Uncle Bob)\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                    CLEAN ARCHITECTURE                               │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│   ┌─────────────────────────────────────────────────────────────┐   │\n│   │  DOMAIN (Enterprise Rules)                                  │   │\n│   │  • entities: Verbatim, Fingerprint, Embedding, Candidate    │   │\n│   │  • valueobjects: MemoryType, RenderMode, RelationType       │   │\n│   │  ✓ No external dependencies                                 │   │\n│   └─────────────────────────────────────────────────────────────┘   │\n│                              ▲                                      │\n│                              │ Dependency                           │\n│   ┌─────────────────────────────────────────────────────────────┐   │\n│   │  USE CASES (Application Rules)                              │   │\n│   │  • StoreMemory, RecallMemory (CBA), LoadMemory              │   │\n│   │  • GetTimeline, GetStatus, GetCausalChain, Archive          │   │\n│   │  • ports: Repository interfaces                             │   │\n│   │  ✓ Depends only on Domain                                   │   │\n│   └─────────────────────────────────────────────────────────────┘   │\n│                              ▲                                      │\n│                              │                                      │\n│   ┌─────────────────────────────────────────────────────────────┐   │\n│   │  INTERFACE ADAPTERS                                         │   │\n│   │  • storage: SQLiteRepository                                │   │\n│   │  • vector: HNSWStore, SQLiteVectorStore                     │   │\n│   │  • extraction: NativeExtractor, CybertronEmbedder           │   │\n│   │  • webhook, metrics                                         │   │\n│   │  ✓ Implements ports                                         │   │\n│   └─────────────────────────────────────────────────────────────┘   │\n│                              ▲                                      │\n│                              │                                      │\n│   ┌─────────────────────────────────────────────────────────────┐   │\n│   │  FRAMEWORKS \u0026 DRIVERS                                       │   │\n│   │  • SQLite3, HNSW lib, Cybertron, MCP Server                 │   │\n│   │  ✓ External technical details                               │   │\n│   └─────────────────────────────────────────────────────────────┘   │\n│                                                                     │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### Project Structure\n\n```\nmira/\n├── cmd/mira/              # Entry point\n├── internal/\n│   ├── domain/            # Domain Layer\n│   │   ├── entities/      # Business entities\n│   │   └── valueobjects/  # Value objects\n│   ├── usecases/          # Use Cases Layer\n│   │   ├── ports/         # Interfaces (Repository, Services)\n│   │   └── interactors/   # Use case implementations\n│   ├── adapters/          # Adapters Layer\n│   │   ├── storage/       # SQLite repository\n│   │   ├── vector/        # HNSW, SQLite vector store, overlap cache\n│   │   ├── extraction/    # NLP, embeddings\n│   │   ├── logging/       # Structured logging\n│   │   ├── webhook/       # HTTP notifications\n│   │   └── metrics/       # Prometheus metrics\n│   ├── interfaces/        # Interfaces Layer\n│   │   └── mcp/           # MCP controller\n│   ├── config/            # Configuration\n│   └── app/               # Composition root (DI)\n│       ├── main.go        # Dependency injection\n│       ├── health.go      # Health checks\n│       ├── health_test.go # Health check tests\n│       └── main_test.go   # Application tests\n├── docs/                  # Documentation\n│   ├── INDEX.md           # Documentation entry point\n│   ├── ARCHITECTURE.md    # Technical deep-dive\n│   ├── FEATURES.md        # Complete feature catalog\n│   └── API_REFERENCES.md  # API reference\n├── SKILL.md               # Agent skill and memory loop guidelines\n├── config.example.yaml    # Example configuration\n└── README.md              # This file\n```\n\n---\n\n## Development\n\n### Testing\n\n```bash\n# Unit tests\ngo test -v ./...\n\n# With race detector\ngo test -race ./...\n\n# Benchmarks\ngo test -bench=. -benchmem ./...\n\n# Coverage\ngo test -cover ./...\n```\n\n### Make Commands\n\n```bash\nmake build       # Build\nmake test        # Tests (with race detector)\nmake test-short  # Quick tests\nmake bench       # Benchmarks\nmake bench-full  # Full benchmarks\nmake run         # Build and run with config.yaml\nmake clean       # Clean build artifacts and data\nmake lint        # Run linters\nmake fmt         # Format code\nmake install     # Install to GOPATH/bin\nmake prepublish VERSION=x.y.z  # Prepare a release\n```\n\n## Changelog\n\n### v0.4.7 (2026-04-24)\n\n- 🚀 New version 0.4.7\n\n### v0.4.6 (2026-04-24)\n\n- 🚀 New version 0.4.6\n\n### v0.4.5 (2026-04-24)\n\n- **Unified SOUL configuration**: Configure all SOUL settings directly inside MIRA's `config.yaml` — no separate process or config file needed for embedded mode. Supports drift threshold, recall budget, extraction confidence, model-swap reinforcement, and evolution history tuning.\n- Uses new `soul.NewApplicationWithDBAndConfig` API for seamless config passthrough.\n\n### v0.4.4 (2026-04-23)\n\n- **SOUL opt-in integration**: MIRA now runs standalone (8 tools) by default. SOUL identity extension must be explicitly enabled via `--with-soul` CLI flag or `soul.enabled: true` in config.\n- SOUL init failures are non-fatal — MIRA gracefully falls back to 8-tool mode.\n\n### v0.4.3 (2026-04-23)\n\n- **Fixed SOUL MCP parameter names**: `agent` → `agent_id`, `model` → `model_id`, `from` → `from_model`, `to` → `to_model`.\n\n### v0.4.2 (2026-04-17)\n\n- **HNSW tuned defaults**: `M` 16 → 32, `ef_search` 50 → 100 for better recall.\n- **Concurrent embedding pool**: Replaced global mutex with model instance pool.\n- **Parallel recall pipeline**: Dense HNSW + lexical FTS5 now execute concurrently.\n- `ef_construction` documented as inactive (not supported by underlying library).\n\nSee [CHANGELOG.md](CHANGELOG.md) for the full release history.\n\n---\n\n## References\n\n### Key Libraries\n\n- [tiktoken-go](https://github.com/pkoukk/tiktoken-go) - OpenAI tokenization\n- Native Go implementation - Rule-based NLP/NER (replaces archived prose)\n- [cybertron](https://github.com/nlpodyssey/cybertron) - Transformer embeddings\n- [hnsw](https://github.com/coder/hnsw) - HNSW graphs\n- [mcp-go](https://github.com/mark3labs/mcp-go) - MCP protocol\n\n### Embedding Model\n\n- **Model:** sentence-transformers/all-MiniLM-L6-v2\n- **Dimensions:** 384\n- **Size:** ~80MB\n- **Performance:** ~1000 texts/sec on CPU\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**MIRA** - _Memory with Information-theoretic Relevance Allocation_\n\n_\"Memory is the sap of artificial intelligence.\"_\n\n[API Reference](docs/API_REFERENCES.md) • [Changelog](CHANGELOG.md)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fmira","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenoitpetit%2Fmira","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fmira/lists"}