Skip to main content

Feature: Git-Native Spaces & OpenMorph Protocol

ARCHIVE — This document is historical reference only. It may contain outdated information. See docs/status.md for current project state.

Date: 2026-02-16 Status: Investigation Phase: 3i (expanded) — Git-Native Spaces Effort: XL (10-14 weeks)


1. Context & Motivation

Problem Statement

Morphee currently has three separate but related systems that need to be unified:

  1. Git-backed memory (Phase 2, DONE) — Stores conversations/facts/preferences in git repos
  2. Git branching (Phase 3i, PLANNED) — Temporal navigation, experimental timelines
  3. PostgreSQL-backed Spaces (current) — Tasks, skills, schedules stored in database

This creates:

  • Data fragmentation — some data in Git, some in PostgreSQL
  • Limited portability — can't easily export/share a complete Space
  • No version control for tasks/skills — only memory is versioned
  • Vendor lock-in — Spaces tied to Morphee's PostgreSQL instance

Vision: OpenMorph Protocol

Transform Morphee from a centralized app to a protocol + reference implementation:

┌─────────────────────────────────────────────────────────┐
│ OpenMorph Protocol │
│ Specification for .morph/ directories │
│ (Any directory with .morph/ becomes a Morph Space) │
└─────────────────────────────────────────────────────────┘
↓ implements
┌─────────────────────────────────────────────────────────┐
│ Morphee.app │
│ Reference implementation: AI layer for .morph/ spaces │
│ Makes directories alive, interactive, explainable │
└─────────────────────────────────────────────────────────┘
↓ works with
┌─────────────────────────────────────────────────────────┐
│ User's Filesystem │
│ ~/Projects/TechCorp/.morph/ │
│ ~/School/Math101/.morph/ │
│ ~/Family/meal-planning/.morph/ │
└─────────────────────────────────────────────────────────┘

Key insight: Just like .git/ makes any directory version-controllable, .morph/ makes any directory AI-augmentable.


2. Options Investigated

Option A: Keep Fragmented (Status Quo)

  • Memory in Git, tasks/skills in PostgreSQL
  • Implement Phase 3i branching for memory only
  • Pros: No migration, simpler short-term
  • Cons: Data fragmentation continues, no portability, limited vision

Option B: Migrate Everything to Git (All-In)

  • ALL Space data (tasks, conversations, skills, config, ACL, vault) lives in Git
  • PostgreSQL only for identity (users, groups, group_members)
  • .morph/ directory structure becomes canonical
  • Pros: Complete portability, version control for everything, federation-ready
  • Cons: Large migration, PostgreSQL becomes cache (complexity)

Option C: Hybrid with Sync Layer

  • Git is source of truth, PostgreSQL is read cache
  • Bidirectional sync: writes go to Git, reads from PostgreSQL for speed
  • .morph/ directories can be local-only OR synced to backend
  • Pros: Best of both worlds, performance + portability
  • Cons: Sync complexity, conflict resolution needed

Incrementally migrate to Git-native Spaces over multiple sub-phases:

  1. Phase 3i.1 — Git branching for memory (as planned)
  2. Phase 3i.2 — Define OpenMorph spec + .morph/ structure
  3. Phase 3i.3 — Extend GitStore for tasks/conversations/skills
  4. Phase 3i.4 — Local discovery + sync modes
  5. Phase 3i.5 — Migration tools + backward compatibility

Pros: Incremental delivery, testable steps, lower risk Cons: Longer timeline, temporary complexity during transition


3. Decision

Chosen approach: Option B (Migrate Everything to Git) - Aggressive Timeline

Reasoning:

  • No users yet → can do breaking changes without impact
  • Faster to full vision (8 weeks vs 10-14 weeks)
  • No backward compatibility burden → cleaner codebase
  • Forced migration → everyone on same system from day one

Trade-offs accepted:

  • Higher risk (all-in migration, no fallback)
  • Breaking change for development database (acceptable)
  • Must get it right first time (thorough testing required)

4. Architecture Design

4.1 OpenMorph Directory Structure

any-directory/                    # User's actual project/folder
├── .morph/ # ← Presence = Morph Space
│ ├── config.yaml # REQUIRED: Space metadata
│ ├── acl.yaml # OPTIONAL: Access control rules
│ ├── vault.enc # OPTIONAL: Encrypted secrets
│ ├── tasks/ # REQUIRED: Tasks as Markdown
│ │ └── task-001.md
│ ├── conversations/ # REQUIRED: AI chat history
│ │ └── conv-001.md
│ ├── memory/ # REQUIRED: Facts, preferences, events
│ │ ├── facts/
│ │ ├── preferences/
│ │ ├── events/
│ │ └── notes/
│ ├── skills/ # OPTIONAL: Dynamic skills
│ │ └── daily-briefing.yaml
│ ├── schedules/ # OPTIONAL: Cron schedules
│ │ └── weekly-backup.yaml
│ └── .git/ # OPTIONAL: Version control
├── src/ # User's files (unchanged)
├── docs/
└── README.md

Key principles:

  • .morph/ is ALONGSIDE user's files, not replacing them
  • Works with existing projects (drop .morph/ into any directory)
  • Git-friendly (designed to version well)
  • Tool-agnostic (any tool can read/write .morph/ if it follows spec)

4.2 config.yaml Schema

# .morph/config.yaml
openmorph_version: "0.1.0"

space:
id: "uuid-or-slug"
name: "TechCorp API Project"
type: "project" # project | personal | team | family | classroom
created_at: "2026-02-16T10:00:00Z"
created_by: "alice@example.com"

# Parent space (for nested spaces)
parent:
path: "../.morph" # Relative path to parent
inherit_acl: true
inherit_integrations: true

# Group (links to Morphee.app backend identity)
group:
id: "group-uuid-123"
name: "TechCorp Engineering"
sync_url: "https://api.morphee.app/sync/group-uuid-123"

# Git configuration
git:
enabled: true
remote_url: "git@gitlab.com:techcorp/api-project.git"
branch: "main"
auto_commit: true
auto_push: false

# Sync mode
sync:
mode: "local-only" # local-only | morphee-hosted | git-remote
backend_url: null
encryption: "group-key"

# Active integrations
integrations:
- llm
- memory
- tasks
- google-calendar

4.3 Three Sync Modes

ModeDescriptionBackendGit RemoteUse Case
local-onlyNever leaves deviceNoneOptional (user manages)Privacy-focused users, offline work
morphee-hostedSynced to Morphee backendapi.morphee.appMorphee's GitLabDefault for new users, easiest
git-remoteUser's Git serverNoneUser-providedPower users, self-hosting, teams

4.4 Database Changes

New table: morph_spaces

CREATE TABLE morph_spaces (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
group_id UUID REFERENCES groups(id) ON DELETE SET NULL,

-- Filesystem location (if user syncs with backend)
local_path TEXT, -- e.g., "/Users/alice/Projects/TechCorp"

-- Git repository URL
git_repo_url TEXT, -- Morphee-hosted OR user's remote

-- Sync mode
sync_mode TEXT CHECK (sync_mode IN ('local-only', 'morphee-hosted', 'git-remote')),

-- Config snapshot (for fast queries)
config JSONB NOT NULL,

-- Status
last_synced_at TIMESTAMPTZ,
sync_status TEXT DEFAULT 'ok', -- ok | syncing | conflict | error

created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, local_path)
);

-- Git commit metadata (for semantic search over history)
CREATE TABLE git_commit_metadata (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
space_id UUID NOT NULL REFERENCES morph_spaces(id) ON DELETE CASCADE,
commit_hash VARCHAR(40) NOT NULL,
branch VARCHAR(100) NOT NULL DEFAULT 'main',
message TEXT NOT NULL,
timestamp TIMESTAMPTZ NOT NULL,
changed_files JSONB NOT NULL DEFAULT '[]',
embedding vector(384), -- For semantic commit search

UNIQUE(space_id, commit_hash)
);

Migration strategy:

  • BREAKING CHANGE: Force migration of all existing Spaces
  • Migration script runs on deploy, converts all Spaces to .morph/ format
  • spaces table deprecated, replaced by morph_spaces

4.5 Backend Components

New modules:

# backend/morph/discovery.py
class MorphDiscoveryService:
async def scan_directory(base_path: str, max_depth: int = 5)list[MorphSpace]
async def register_morph_space(user: User, local_path: str, sync_mode: str) → MorphSpace
async def sync_local_to_backend(space_id: UUID) → SyncResult

# backend/morph/sync.py
class MorphSyncService:
async def sync_git_to_postgres(space_id: UUID)None # For fast queries
async def sync_postgres_to_git(space_id: UUID)None # On user edits
async def resolve_conflicts(space_id: UUID, strategy: str) → ConflictResolution

# backend/morph/exporter.py
class MorphExporter:
async def export_space_to_morph(space_id: UUID, target_path: str) → Path
async def import_morph_to_space(morph_path: str) → UUID

Extended GitStore:

# backend/memory/git_store.py (extended)
class GitStore:
# Existing: save_conversation, save_memory, sync

# NEW: Branching (Phase 3i.1)
async def create_branch(group_id, space_id, name, from_commit=None)str
async def switch_branch(group_id, space_id, name)str
async def list_branches(group_id, space_id)list[BranchInfo]
async def merge_branch(group_id, space_id, source, target) → MergeResult

# NEW: Extended data types (Phase 3i.3)
async def save_task(group_id, space_id, task_id, task_data)str
async def save_skill(group_id, space_id, skill_id, skill_data)str
async def save_config(group_id, space_id, config)str
async def save_acl(group_id, space_id, acl)str

4.6 Tauri Commands

// frontend/src-tauri/src/commands/morph_commands.rs

#[tauri::command]
async fn morph_init(path: String, config: MorphConfig)Result<(), MorpheeError>

#[tauri::command]
async fn morph_discover(base_path: String, max_depth: u32)Result<Vec<MorphSpace>, MorpheeError>

#[tauri::command]
async fn morph_read_config(morph_path: String)Result<MorphConfig, MorpheeError>

#[tauri::command]
async fn morph_register(local_path: String, sync_mode: String)Result<String, MorpheeError>

4.7 Frontend UI

New pages:

  1. Space Discovery (pages/SpaceDiscovery.tsx)

    • Scan filesystem for .morph/ directories
    • Show list of discovered Spaces
    • Option to register with backend or keep local
  2. Morph Init Dialog (components/morph/MorphInitDialog.tsx)

    • Choose directory
    • Configure sync mode
    • Initialize .morph/ structure
  3. Sync Settings (pages/settings/SyncTab.tsx)

    • Per-Space sync mode
    • Conflict resolution UI
    • Sync status indicators

5. Implementation Plan (Aggressive - 8 weeks)

Phase 3i.1: Git Branching + OpenMorph Spec — 2 weeks

Goal: Branching for memory + define .morph/ structure (parallel work).

StepDescriptionEffortDependencies
1.1Backend: Extend GitStore with branch operationsMNone
1.2Backend: git_commit_metadata table + migrationXSStep 1.1
1.3Backend: MemoryIntegration branch actionsMStep 1.1
1.4Tauri: git2 branch operations in RustMStep 1.1
1.5Write SPECIFICATION.md (in docs/features/)SParallel
1.6Define JSON Schemas for config/acl/tasksSStep 1.5
1.7Create example .morph/ directoriesXSStep 1.6
1.8Tests: Branching operationsMSteps 1.1-1.4

Deliverable: Git branching works + OpenMorph spec defined.

Phase 3i.2: Full GitStore Migration (BREAKING) — 3 weeks

Goal: ALL Space data (tasks, skills, config, ACL) in Git. PostgreSQL = cache only.

StepDescriptionEffortDependencies
2.1Define task Markdown schemaSPhase 3i.1
2.2Define skill/schedule YAML schemasSStep 2.1
2.3Backend: GitStore save_task/skill/config/aclLStep 2.2
2.4Tauri: Rust GitStore extensionsMStep 2.3
2.5Backend: Sync layer (Git → Postgres cache)MStep 2.3
2.6Backend: Sync layer (Postgres → Git write)MStep 2.5
2.7Database migration: morph_spaces tableSStep 2.3
2.8Migration script: Convert all existing SpacesMStep 2.7
2.9Update all services (TaskService, SkillService, etc.)LStep 2.8
2.10Tests: Full CRUD cycle for all data typesLAll above

Deliverable: Complete Spaces stored in Git, PostgreSQL is cache.

Phase 3i.3: Discovery + Sync Modes — 2 weeks

Goal: Morphee.app discovers .morph/ on filesystem, supports 3 sync modes.

StepDescriptionEffortDependencies
3.1Backend: MorphDiscoveryServiceMPhase 3i.2
3.2Backend: Register/sync endpointsMStep 3.1
3.3Tauri: morph_discover commandMStep 3.1
3.4Tauri: morph_init commandMStep 3.3
3.5Frontend: SpaceDiscovery pageMStep 3.3
3.6Frontend: MorphInitDialogMStep 3.4
3.7Backend: Sync modes (local/hosted/remote)MStep 3.2
3.8Tests: Discovery + sync flowsMAll above

Deliverable: Users can drop .morph/ anywhere, choose sync mode.

Phase 3i.4: Polish + Timeline UI — 1 week

Goal: Timeline visualization, conflict resolution, final cleanup.

StepDescriptionEffortDependencies
4.1Frontend: TimelineRenderer componentMPhase 3i.3
4.2Frontend: MemoryTimeline pageMStep 4.1
4.3Frontend: Branch selector UISStep 4.2
4.4Frontend: Conflict resolution dialogMStep 4.3
4.5Backend: Commit embedding pipelineSPhase 3i.2
4.6Documentation: User guide + API docsSAll above
4.7Final integration testsMAll above

Deliverable: Production-ready Git-native Spaces with full UI.


6. Effort Summary

PhaseSizeDuration
3i.1 (Branching + Spec)M2 weeks
3i.2 (Full Migration)L3 weeks
3i.3 (Discovery + Sync)M2 weeks
3i.4 (Polish + UI)M1 week
TOTALL-XL8 weeks

7. Questions & Answers

Q1: Should we rename Phase 3i?

A: Yes. Rename from "Memory Enhancement" to "Git-Native Spaces & OpenMorph" to reflect broader scope.

Q2: Should OpenMorph spec be a separate repository?

A: No, not initially. Keep in docs/features/openmorph/ until implementation proven. Public repo later when ready for partners.

Q3: Priority: Memory branching or .morph/ first?

A: Memory branching first (Phase 3i.1). It's smaller, delivers value immediately, builds foundation for later phases.

Q4: Migration: Convert existing Spaces automatically?

A: YES. Force migration on deploy. No users yet, so acceptable breaking change. Migration script converts all Spaces automatically.

Q5: What happens to PostgreSQL?

A: Becomes identity layer (users, groups) + read cache for fast queries. Git is source of truth for Space data.

Q6: Can users manually edit .morph/ files?

A: YES! This is a key feature. Power users can vim tasks/task-001.md, commit with git, Morphee syncs it.

Q7: What about real-time collaboration?

A: Not in this phase. Future: operational transforms or CRDT layer on top of Git. For now: last-write-wins + conflict UI.

Q8: GPG signing (from earlier discussion)?

A: Phase 3i.6 (future). Add signed commits, ACL in Git, vault encryption. Don't block this phase on crypto.


8. Risks & Mitigations

RiskMitigation
Git conflicts too complexStart with simple strategies (last-write-wins, ours/theirs). Manual resolution UI in Phase 3i.5
Sync performancePostgreSQL cache for reads. Only sync on write. Background job for conflict-free sync
User confusion (Git concepts)Hide Git details in UI. Show "timeline", "experimental ideas", not "branches"
Data loss during migrationExtensive testing. Backup before convert. Rollback option. Export tool always available
OpenMorph fragmentationStrict semver. Breaking changes only in major versions. Reference implementation (Morphee.app) sets standard

9. Open Items

  • Decide on conflict resolution strategy — last-write-wins, manual UI, or AI-mediated?
  • Define OpenMorph versioning policy — semver, deprecation timeline
  • Partner outreach — which tools to target first (VS Code, Obsidian, Notion)?
  • Performance benchmarks — how big can .morph/ get before slowdown?
  • Mobile considerations — does .morph/ work on iOS/Android filesystem?

10. Success Metrics

MetricTarget
Adoption50% of new Spaces created as .morph/ within 3 months
Migration25% of existing Spaces converted within 6 months
Partners2+ third-party tools implementing OpenMorph within 1 year
PerformanceSpace sync <5s for typical Space (~100 tasks, 50 conversations)
Reliability<1% data loss rate during sync/migration

11. References

Internal

External


Next Steps:

  1. Review this proposal with team
  2. Get approval on phased approach
  3. Start Phase 3i.1 (Git Branching) implementation
  4. Draft OpenMorph SPECIFICATION.md during Phase 3i.1
  5. Publish spec, announce to community

Last Updated: 2026-02-16