README.md
markdown
| 1 | # Muse |
| 2 | |
| 3 | > **A domain-agnostic version control system for multidimensional state.** |
| 4 | |
| 5 | Git works on text because text is one-dimensional — a sequence of lines. Diffs are additions and deletions to that sequence. |
| 6 | |
| 7 | Muse works on *any* state space where a "change" is a delta across multiple axes simultaneously. Music is the first domain. It is not the definition. |
| 8 | |
| 9 | --- |
| 10 | |
| 11 | ## The Core Abstraction |
| 12 | |
| 13 | Strip Muse down to its invariants and what remains is: |
| 14 | |
| 15 | ``` |
| 16 | State = a serializable, content-addressed snapshot of any multidimensional space |
| 17 | Commit = a named delta from a parent state, recorded in a DAG |
| 18 | Branch = a divergent line of intent forked from a shared ancestor |
| 19 | Merge = three-way reconciliation of two divergent state lines against a common base |
| 20 | Drift = the gap between committed state and live state |
| 21 | Checkout = deterministic reconstruction of any historical state from the DAG |
| 22 | Lineage = the causal chain from root to any commit |
| 23 | ``` |
| 24 | |
| 25 | None of those definitions contain the word "music." |
| 26 | |
| 27 | --- |
| 28 | |
| 29 | ## Plugin Architecture |
| 30 | |
| 31 | A domain plugin implements six interfaces. Muse provides the rest — the DAG engine, content-addressed object store, branching, lineage walking, topological log graph, and merge base finder. |
| 32 | |
| 33 | ```python |
| 34 | class MuseDomainPlugin(Protocol): |
| 35 | def snapshot(self, live_state: LiveState) -> StateSnapshot: |
| 36 | """Capture current live state as a serializable, hashable snapshot.""" |
| 37 | |
| 38 | def diff( |
| 39 | self, |
| 40 | base: StateSnapshot, |
| 41 | target: StateSnapshot, |
| 42 | *, |
| 43 | repo_root: pathlib.Path | None = None, |
| 44 | ) -> StateDelta: |
| 45 | """Compute the typed delta between two snapshots.""" |
| 46 | |
| 47 | def merge( |
| 48 | self, |
| 49 | base: StateSnapshot, |
| 50 | left: StateSnapshot, |
| 51 | right: StateSnapshot, |
| 52 | *, |
| 53 | repo_root: pathlib.Path | None = None, |
| 54 | ) -> MergeResult: |
| 55 | """Three-way merge. Return merged snapshot + conflict report.""" |
| 56 | |
| 57 | def drift(self, committed: StateSnapshot, live: LiveState) -> DriftReport: |
| 58 | """Compare committed state against current live state.""" |
| 59 | |
| 60 | def apply(self, delta: StateDelta, live_state: LiveState) -> LiveState: |
| 61 | """Apply a delta to produce a new live state (checkout execution).""" |
| 62 | |
| 63 | def schema(self) -> DomainSchema: |
| 64 | """Declare the structural shape of this domain's data.""" |
| 65 | ``` |
| 66 | |
| 67 | Two optional protocol extensions unlock richer merge semantics: |
| 68 | |
| 69 | ```python |
| 70 | class StructuredMergePlugin(MuseDomainPlugin, Protocol): |
| 71 | """Sub-file auto-merge using Operational Transformation.""" |
| 72 | def merge_ops(self, base, ours_snap, theirs_snap, ours_ops, theirs_ops, ...) -> MergeResult: ... |
| 73 | |
| 74 | class CRDTPlugin(MuseDomainPlugin, Protocol): |
| 75 | """Convergent multi-agent join — no conflict state ever exists.""" |
| 76 | def join(self, a: CRDTSnapshotManifest, b: CRDTSnapshotManifest) -> CRDTSnapshotManifest: ... |
| 77 | def crdt_schema(self) -> list[CRDTDimensionSpec]: ... |
| 78 | def to_crdt_state(self, snapshot: StateSnapshot) -> CRDTSnapshotManifest: ... |
| 79 | def from_crdt_state(self, crdt: CRDTSnapshotManifest) -> StateSnapshot: ... |
| 80 | ``` |
| 81 | |
| 82 | The music plugin — the reference implementation — implements all six interfaces and both optional extensions for MIDI state. Every other domain is a new plugin. |
| 83 | |
| 84 | --- |
| 85 | |
| 86 | ## Music — The Reference Implementation |
| 87 | |
| 88 | Music is the domain that proved the abstraction. State is a snapshot of MIDI files on disk. Diff is file-level set difference plus note-level Myers LCS diff inside each MIDI file. Merge is three-way reconciliation across five musical dimensions (melodic, rhythmic, harmonic, dynamic, structural), each diffed with the algorithm best suited to its structure. Drift compares the committed snapshot against the live working tree. Checkout incrementally applies the delta between snapshots using the plugin. |
| 89 | |
| 90 | ```bash |
| 91 | # Initialize a Muse repository (default domain: music) |
| 92 | muse init |
| 93 | |
| 94 | # Commit the current working tree |
| 95 | muse commit -m "Add verse melody" |
| 96 | |
| 97 | # Create and switch to a new branch |
| 98 | muse checkout -b feature/chorus |
| 99 | |
| 100 | # View commit history as an ASCII graph |
| 101 | muse log --graph |
| 102 | |
| 103 | # Show uncommitted changes vs HEAD |
| 104 | muse status |
| 105 | |
| 106 | # Three-way merge a branch (OT merge when both branches have typed deltas) |
| 107 | muse merge feature/chorus |
| 108 | |
| 109 | # Cherry-pick a specific commit |
| 110 | muse cherry-pick <commit-id> |
| 111 | |
| 112 | # Revert a commit (creates a new commit undoing the change) |
| 113 | muse revert <commit-id> |
| 114 | |
| 115 | # Show a commit's metadata and note-level operation list |
| 116 | muse show [<ref>] [--json] [--stat] |
| 117 | |
| 118 | # Domain plugin dashboard — list registered domains and capabilities |
| 119 | muse domains |
| 120 | |
| 121 | # Scaffold a new domain plugin |
| 122 | muse domains --new <domain-name> |
| 123 | ``` |
| 124 | |
| 125 | Run `muse --help` for the full command list. |
| 126 | |
| 127 | --- |
| 128 | |
| 129 | ## Domain Instantiations |
| 130 | |
| 131 | ### Music *(reference implementation)* |
| 132 | MIDI state across notes, velocities, controller events, pitch bends, and aftertouch. Typed delta algebra surfaces note-level inserts, deletes, and replaces in `muse show`. Three-way merge reconciles divergent takes across five musical dimensions. **Ships with full DAG, branching, OT merge, CRDT semantics, and E2E tests.** |
| 133 | |
| 134 | ### Scientific Simulation *(planned)* |
| 135 | A climate model is a multidimensional state space: temperature, pressure, humidity, ocean current, ice coverage at every grid point. Commit a named checkpoint. Branch to explore a parameter variation. Merge two teams' adjustments against a common baseline run. Drift detection flags when a running simulation has diverged from its last committed checkpoint. |
| 136 | |
| 137 | ### Genomics *(planned)* |
| 138 | A genome under CRISPR editing is a high-dimensional sequence state. Each editing session is a commit. Alternate intervention strategies are branches. When two research teams converge on the same baseline organism and apply different edits, merge reconciles those edit sets against the common ancestor genome. The Muse DAG becomes the provenance record of every edit. |
| 139 | |
| 140 | ### 3D Spatial Design *(planned)* |
| 141 | Architecture, urban planning, game world construction. Branch to explore "what if we moved the load-bearing wall." Merge the structural engineer's changes and the lighting consultant's changes against the architect's baseline. Drift detection surfaces the delta between the committed design and the as-built state. |
| 142 | |
| 143 | ### Spacetime *(theoretical)* |
| 144 | A spacetime plugin models state as a configuration of matter-energy distribution across a coordinate grid. A commit is a named configuration at a set of coordinates. A branch is a counterfactual — what would the state space look like if this mass had been positioned differently at T₀. |
| 145 | |
| 146 | This is exactly what large-scale physics simulation does, without the version control semantics. Adding Muse semantics — content-addressed states, causal lineage, merge — makes simulation runs composable in a way they currently are not. Two simulations that share a common initialization can be merged or compared with the same rigor that two branches of a codebase can. |
| 147 | |
| 148 | Whether this scales to actual spacetime is a question for physics. Whether it applies to spacetime *simulation* is just engineering. |
| 149 | |
| 150 | --- |
| 151 | |
| 152 | ## Agent Collaboration |
| 153 | |
| 154 | Muse's most transformative application is **shared persistent memory for teams of collaborating agents**. |
| 155 | |
| 156 | Without a shared state store, collaborating agents are stateless with respect to each other. Each agent knows what it has done; none knows what the others have committed, branched, or abandoned. There is no canonical record of what has happened. |
| 157 | |
| 158 | Muse solves this at the protocol level. Every agent in a tree sees the same DAG. An agent can: |
| 159 | |
| 160 | - Read the full commit history to understand what has been tried |
| 161 | - Branch from any commit to explore an alternative without polluting the main line |
| 162 | - Commit its work with a message that becomes part of the permanent record |
| 163 | - Merge its branch back, with three-way reconciliation handling conflicts |
| 164 | - Check out any historical state to understand what the system looked like at any prior point |
| 165 | |
| 166 | For high-throughput agent scenarios, CRDT mode enables convergent multi-agent writes with no conflict state — every `muse merge` always succeeds, regardless of how many agents write concurrently. |
| 167 | |
| 168 | A tree of musical agents with distinct cognitive identities, collaborating over a shared Muse repository: |
| 169 | |
| 170 | ``` |
| 171 | Composer (root coordinator) |
| 172 | ├── Bach agent — commits fugue subject on branch counterpoint/main |
| 173 | ├── Jimi Hendrix agent — commits lead response on branch lead/main |
| 174 | └── Miles Davis agent — commits harmonic reframing on branch modal/main |
| 175 | ``` |
| 176 | |
| 177 | The Composer runs a three-way merge. Conflicts are real musical conflicts — two agents wrote to the same beat, the same frequency range, the same structural moment. The Composer's cognitive architecture resolves them. With CRDT mode enabled, the join always converges without conflict. |
| 178 | |
| 179 | --- |
| 180 | |
| 181 | ## Repository Structure |
| 182 | |
| 183 | ``` |
| 184 | muse/ |
| 185 | domain.py — MuseDomainPlugin Protocol + StructuredMergePlugin + CRDTPlugin |
| 186 | core/ |
| 187 | store.py — file-based commit/snapshot/tag store (no external DB) |
| 188 | repo.py — repository detection (directory walk or MUSE_REPO_ROOT) |
| 189 | snapshot.py — content-addressed snapshot and commit ID derivation |
| 190 | object_store.py — SHA-256 blob storage under .muse/objects/ |
| 191 | merge_engine.py — three-way merge state machine + CRDT join entry point |
| 192 | op_transform.py — Operational Transformation for operation-level merge |
| 193 | schema.py — DomainSchema TypedDicts for algorithm selection |
| 194 | attributes.py — .museattributes TOML parser and strategy resolver |
| 195 | errors.py — exit codes and error primitives |
| 196 | diff_algorithms/ — Myers LCS, tree-edit, numerical, set-ops diff library |
| 197 | crdts/ — VectorClock, LWWRegister, ORSet, RGA, AWMap, GCounter |
| 198 | plugins/ |
| 199 | registry.py — maps domain names → MuseDomainPlugin instances |
| 200 | music/ — music domain plugin (reference implementation) |
| 201 | plugin.py — implements all six MuseDomainPlugin interfaces |
| 202 | midi_diff.py — note-level MIDI diff and reconstruction |
| 203 | scaffold/ — copy-paste template for new domain plugins |
| 204 | plugin.py — fully typed starter with TODO markers |
| 205 | cli/ |
| 206 | app.py — Typer application root |
| 207 | config.py — .muse/config.toml read/write helpers |
| 208 | commands/ — one file per subcommand (15 commands) |
| 209 | |
| 210 | tests/ |
| 211 | test_cli_*.py — CLI integration tests (one per command group) |
| 212 | test_core_*.py — core engine unit tests |
| 213 | test_crdts.py — CRDT primitive lattice law and integration tests |
| 214 | test_op_transform.py — Operational Transformation tests |
| 215 | test_diff_algorithms.py — diff algorithm library tests |
| 216 | test_music_plugin.py |
| 217 | test_plugin_registry.py |
| 218 | |
| 219 | docs/ |
| 220 | architecture/ — architecture reference and E2E walkthrough |
| 221 | guide/ — plugin authoring guide and CRDT reference |
| 222 | protocol/ — MuseDomainPlugin protocol spec and domain concepts |
| 223 | reference/ — type contracts, .museattributes format, .museignore |
| 224 | demo/ — tour de force narration script |
| 225 | ``` |
| 226 | |
| 227 | --- |
| 228 | |
| 229 | ## Installation |
| 230 | |
| 231 | ```bash |
| 232 | # From source (recommended during v0.1.x development) |
| 233 | git clone https://github.com/cgcardona/muse |
| 234 | cd muse |
| 235 | pip install -e ".[dev]" |
| 236 | ``` |
| 237 | |
| 238 | Core dependencies: |
| 239 | |
| 240 | - Python 3.11+ |
| 241 | - Typer (CLI) |
| 242 | - mido (MIDI parsing, music plugin only) |
| 243 | - toml |
| 244 | |
| 245 | No database required. Muse stores all state in the `.muse/` directory — objects, snapshots, commits, refs — exactly like Git stores state in `.git/`. |
| 246 | |
| 247 | --- |
| 248 | |
| 249 | ## Documentation |
| 250 | |
| 251 | - [Architecture](docs/architecture/muse-vcs.md) — full technical design and module map (v0.1.1) |
| 252 | - [Plugin Authoring Guide](docs/guide/plugin-authoring-guide.md) — step-by-step guide for building a new domain plugin |
| 253 | - [CRDT Reference](docs/guide/crdt-reference.md) — CRDT primer and API reference for all six primitives |
| 254 | - [E2E Walkthrough](docs/architecture/muse-e2e-demo.md) — step-by-step lifecycle from `init` to merge conflict |
| 255 | - [Plugin Protocol](docs/protocol/muse-protocol.md) — language-agnostic `MuseDomainPlugin` specification |
| 256 | - [Domain Concepts](docs/protocol/muse-domain-concepts.md) — universal terms, cross-domain patterns, and music-specific vocabulary |
| 257 | - [Type Contracts](docs/reference/type-contracts.md) — named type definitions with Mermaid diagrams |
| 258 | - [`.museattributes` Reference](docs/reference/muse-attributes.md) — per-repo merge strategy overrides (TOML format) |
| 259 | - [`.museignore` Reference](docs/reference/museignore.md) — snapshot exclusion rules |
| 260 | |
| 261 | --- |
| 262 | |
| 263 | *Built from the couch. March 2026.* |