Git Memory Branching & Commit Search — Design Document
ARCHIVE — This document is historical reference only. It may contain outdated information. See docs/status.md for current project state.
Created: February 13, 2026 Status: Planned Phase: 3i (Memory Enhancement)
Overview
Extend Morphee's git-backed memory system (Phase 2) with branching, visualization, and searchable commit history. Enables temporal navigation ("what did I know last month?"), experimental timelines ("vacation planning branch"), and semantic search over memory evolution.
Motivation
Problem: The current memory system (Phase 2) is linear — memories accumulate chronologically in a single git timeline. Users can't:
- Explore "what-if" scenarios without affecting their main memory
- Easily navigate to past memory states
- Search for when they last discussed a topic
Solution: Add git branching + commit search:
- Branches — Create parallel memory timelines (main, experiments, archives)
- Commit search — Embed commits in LanceDB, search by semantic query + time
- Branch visualization — Timeline UI showing branch divergence, merge points
- Temporal RAG — Query memory as it existed at a specific point in time
Use Cases
| User | Scenario |
|---|---|
| Parent (Sophie) | "Show me my main schedule" vs "Show me the vacation planning timeline" — separate work from exploration |
| Teacher (Emma) | Create a "Fall 2026 semester" branch, experiment with lesson plans, merge selected ones to main after testing |
| Manager (Julie) | "Create a branch for Project Phoenix planning" — iterate on ideas without cluttering team's main memory |
| Grandparent (Jeanne) | "What did I know about Christmas planning last month?" — temporal navigation to see past state |
Architecture
Backend: GitStore Extension
Current (backend/memory/git_store.py):
class GitStore:
async def init_repo(group_id) → Path
async def save_conversation(group_id, conversation_id, messages, title) → str
async def save_memory(group_id, memory_id, content, memory_type, scope) → str
async def delete_memory(group_id, memory_id, memory_type, scope) → bool
async def sync(group_id) → SyncResult # push/pull if remote configured
Phase 3i additions:
class GitStore:
# Branch operations
async def create_branch(group_id: UUID, branch_name: str, from_commit: str | None = None) → str
async def switch_branch(group_id: UUID, branch_name: str) → str # returns commit hash
async def list_branches(group_id: UUID) → list[BranchInfo]
async def merge_branch(group_id: UUID, source: str, target: str, strategy: str = "manual") → MergeResult
async def get_commit_history(group_id: UUID, branch: str | None = None, limit: int = 50) → list[CommitInfo]
# Commit metadata
async def get_commit_diff(group_id: UUID, commit_hash: str) → DiffResult
async def checkout_commit(group_id: UUID, commit_hash: str) → str # detached HEAD for temporal queries
Data models:
class BranchInfo(BaseModel):
name: str
commit: str # HEAD commit hash
is_active: bool
created_at: datetime
class CommitInfo(BaseModel):
hash: str
message: str
timestamp: datetime
branch: str
changed_files: list[str]
author: str = "Morphee"
class MergeResult(BaseModel):
merged: bool
commit: str | None # merge commit hash if successful
conflicts: list[ConflictInfo]
merged_count: int
Database: Commit Metadata Table
CREATE TABLE git_commit_metadata (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
commit_hash VARCHAR(40) NOT NULL,
branch VARCHAR(100) NOT NULL,
message TEXT NOT NULL,
timestamp TIMESTAMPTZ NOT NULL,
changed_files JSONB NOT NULL DEFAULT '[]',
embedding vector(384), -- LanceDB embedding for semantic search
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(group_id, commit_hash)
);
CREATE INDEX idx_commit_metadata_group_branch ON git_commit_metadata(group_id, branch);
CREATE INDEX idx_commit_metadata_timestamp ON git_commit_metadata(group_id, timestamp DESC);
CREATE INDEX idx_commit_embedding ON git_commit_metadata USING ivfflat (embedding vector_cosine_ops);
Memory Integration Extension
New actions:
class MemoryIntegration(BaseInterface):
# ... existing: search, store, recall, forget
async def create_branch(self, ctx: ExecutionContext, name: str, from_commit: str | None = None)
async def switch_branch(self, ctx: ExecutionContext, name: str)
async def search_history(self, ctx: ExecutionContext, query: str, time_range: dict | None, branch: str | None, limit: int = 10)
async def merge_branch(self, ctx: ExecutionContext, source: str, target: str, strategy: str = "manual")
Frontend: Timeline UI
New page: frontend/src/pages/MemoryTimeline.tsx
Components:
- TimelineRenderer (Tier 2 component) — Visual git log with branch graph
- CommitDetailDialog — Shows commit message, changed files, diff view
- BranchSelector (dropdown) — Shows current branch + all branches
- Historical context badge — "Viewing: 2 weeks ago (detached)"
Tauri Rust: git2 Branching
Extensions to frontend/src-tauri/src/git_store.rs:
impl GitStore {
pub fn create_branch(&self, group_id: &str, branch_name: &str, from_commit: Option<&str>) → Result<String>
pub fn switch_branch(&self, group_id: &str, branch_name: &str) → Result<String>
pub fn list_branches(&self, group_id: &str) → Result<Vec<BranchInfo>>
pub fn merge_branch(&self, group_id: &str, source: &str, target: &str, strategy: &str) → Result<MergeResult>
}
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/memory/branches | POST | Create branch |
/api/memory/branches/switch | POST | Switch active branch |
/api/memory/branches | GET | List all branches |
/api/memory/search-history | POST | Search commits semantically |
/api/memory/branches/merge | POST | Merge branches |
/api/memory/commits/{hash} | GET | Get commit details + diff |
/api/memory/checkout/{hash} | POST | Checkout commit (detached HEAD) |
Effort Estimation
| Task | Size | Notes |
|---|---|---|
| Backend: GitStore branching (Python) | M | create, switch, list, merge, checkout |
| Backend: git_commit_metadata table + migration | XS | SQL schema |
| Backend: Commit embedding pipeline | S | Extend MemorySyncScheduler |
| Backend: MemoryIntegration actions | M | 4 new actions + tests |
| Backend: Branch-aware RAG | S | Add branch param to search() |
| Tauri: git_store.rs branching (Rust) | M | git2 branch operations |
| Frontend: TimelineRenderer component | M | Git graph visualization |
| Frontend: MemoryTimeline page | M | Commit list, detail, navigation |
| Frontend: Branch selector UI | S | Dropdown in chat/memory views |
| Tests: Backend + Tauri + Frontend | M | 50+ tests total |
Total: Large (3-4 weeks)
Risks & Mitigations
| Risk | Mitigation |
|---|---|
| Git conflicts too complex for AI/user | Start with simple strategies ("ours", "theirs"), defer manual conflict resolution UI to later iteration |
| Detached HEAD confusion | Clear UI indicator ("Viewing past memory — Back to present" button) |
| Branch proliferation clutter | Add archive/delete branch actions, suggest cleanup in onboarding |
| Performance: embedding all commits | Background job, rate-limited. Only embed commits since last sync |
Future Enhancements
Core Features
- Automatic branching — AI suggests creating a branch when user says "let's explore this idea"
- Branch templates — Pre-configured branches for common scenarios (vacation, project, semester)
- Cross-branch diff view — Compare memory state across branches visually
- Conflict resolution UI — Side-by-side diff editor for manual merge
- Branch search — "Find branches related to vacation" → semantic search across branch names and commit history
- Branch lifecycle — Auto-archive branches after inactivity, scheduled cleanup
ACL & Permission Enhancements
Branch Permissions (leveraging existing PermissionPolicy):
class BranchPermission(BaseModel):
branch_pattern: str # "main", "personal/*", "experiments/*"
can_create: list[str] # ["parent", "teacher"]
can_merge: list[str] # ["parent"]
can_delete: list[str] # ["parent"]
can_view: list[str] # ["parent", "child", "guest"]
require_approval: bool # Merge requires approval from approvers list
approvers: list[str] # User IDs or roles who can approve merges
Use cases:
-
Family scenario:
- Kids can create branches under
personal/{kid_name}/*but only read frommain - Parents can merge any branch to
main - Family decisions require parent approval before merging
- Kids can create branches under
-
Classroom scenario:
- Students create branches per assignment:
students/{name}/assignment-1 - Teacher can view all student branches (read-only)
- Students can't see other students' branches
- Teacher merges approved work to
class-main
- Students create branches per assignment:
-
Team scenario:
- Developers create feature branches:
features/{feature-name} - Any team member can merge to
develop - Manager approval required to merge to
main
- Developers create feature branches:
Branch Visibility:
- Private branches: Only creator + admins can see (e.g., "Mom's surprise party planning")
- Shared branches: Visible to group members based on roles
- Public branches: Visible to all group members (default)
Audit Trail:
- Log all branch operations with attribution: who created, who merged, who deleted
- Stored in
git_branch_operationstable:{user_id, branch, operation, timestamp, approved_by?, commit_hash} - Query: "Who merged the vacation branch last week?" → shows audit trail
Advanced Memory Features
Memory Permissions Per Branch:
- Different RAG contexts per user role within same branch
- Example: Kid sees age-appropriate memories, parent sees everything
- Implemented via
PermissionPolicyonMemoryIntegration.searchwith branch + role context
Branch-Specific Retention:
- Automatic memory decay on experimental branches (older than 30 days deleted)
- Main branch has indefinite retention
- Archive branches compressed (embeddings removed, only Markdown kept)
Collaborative Branching:
- Multiple users can work on same branch simultaneously
- Real-time conflict detection: "Mom is editing vacation plans on this branch right now"
- Merge conflict resolution via AI mediation: "Mom wants Paris, Dad wants Rome — let's discuss"
Memory Branch Notifications:
- "Your vacation planning branch has 3 new commits from Mom"
- "Experimental meal plan branch ready for review — merge to main?"
- Integration with NotificationsIntegration
Branch Subscriptions:
- Subscribe to branch changes (like GitHub watch)
- Receive notification when branch is updated
- User table:
branch_subscriptions JSONB→[{branch: "vacation", notify: true}]
AI-Powered Enhancements
Smart Merge Suggestions:
- AI analyzes two branches and suggests best merge strategy
- "These memories are complementary — safe auto-merge"
- "Conflict detected: Mom scheduled dentist Tuesday 2pm, you have soccer practice same time"
Branch Summarization:
- "Summarize what changed in vacation-planning branch" → AI reads commits, generates summary
- Useful before merging: "Review changes before merging to main"
Temporal Queries Across Branches:
- "Compare my main timeline vs experimental timeline 2 weeks ago"
- "Show me all branches where we discussed Christmas planning"
Branch Recommendations:
- AI suggests creating a branch: "This seems like a big decision — want to explore in a separate branch?"
- AI suggests merging: "Your meal prep experiments look good — ready to merge to main?"
Integration with Existing Systems
Branch-Aware Skills (Phase 3b.1 Dynamic Skills):
- Skills can specify which branch to use:
{branch: "experiments"} - Cron jobs can run on specific branches: "Daily backup skill runs on main only"
Branch-Aware Spaces (existing Space system):
- Each Space can have a default branch: "Homework space always uses student's personal branch"
- Space inheritance: sub-Space inherits parent's branch unless overridden
Branch-Based Sandboxing:
- Test AI changes in a branch before applying to main
- "Try this new scheduling algorithm in experimental branch first"
Last Updated: February 13, 2026