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 MIDI plugin — the reference implementation — implements all six interfaces and both optional extensions for MIDI state. The code plugin is the second shipped domain. Every other domain is a new plugin. |
| 83 | |
| 84 | --- |
| 85 | |
| 86 | ## MIDI — The Reference Implementation |
| 87 | |
| 88 | MIDI 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 **21 independent MIDI dimensions** — notes, pitch bend, channel pressure, polyphonic aftertouch, 11 named CC controllers (modulation, volume, pan, expression, sustain, portamento, sostenuto, soft pedal, reverb, chorus, other), program changes, tempo map, time signatures, key signatures, markers, and track structure — each independently mergeable so two agents editing different aspects of the same file never conflict. 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: midi) |
| 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 | ### MIDI *(reference implementation)* |
| 132 | MIDI state across all 21 fine-grained dimensions: notes, pitch bend, per-note polyphonic aftertouch, 11 named CC controllers, program changes, tempo map, time signatures, key signatures, section markers, and track structure. Typed delta algebra surfaces note-level inserts, deletes, and replaces in `muse show`. Three-way merge operates per-dimension — two agents editing sustain pedal and pitch bend simultaneously never produce a conflict. Stable entity identity tracks notes across edits. **Ships with full DAG, branching, OT merge, CRDT semantics, voice-aware RGA, MIDI query DSL, invariant enforcement, and E2E tests.** |
| 133 | |
| 134 | ### Code *(second domain — shipped)* |
| 135 | Source code as a graph of named symbols — functions, classes, methods — rather than a sequence of lines. Two commits that only reformat a file produce no structured delta. Renames and moves are detected via content-addressed symbol identity. Three-way merge operates at symbol granularity — two agents editing different functions in the same file auto-merge without conflict. Supports Python, TypeScript, JavaScript, Go, Rust, Java, C, C++, C#, Ruby, and Kotlin via `tree-sitter` ASTs. **Ships with symbol diff, code query DSL, semantic hotspots, coupling analysis, refactor detection, and `.museattributes` integration at both file and symbol level.** |
| 136 | |
| 137 | ### Scientific Simulation *(planned)* |
| 138 | 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. |
| 139 | |
| 140 | ### Genomics *(planned)* |
| 141 | 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. |
| 142 | |
| 143 | ### 3D Spatial Design *(planned)* |
| 144 | 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. |
| 145 | |
| 146 | ### Spacetime *(theoretical)* |
| 147 | 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₀. |
| 148 | |
| 149 | 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. |
| 150 | |
| 151 | Whether this scales to actual spacetime is a question for physics. Whether it applies to spacetime *simulation* is just engineering. |
| 152 | |
| 153 | --- |
| 154 | |
| 155 | ## Agent Collaboration |
| 156 | |
| 157 | Muse's most transformative application is **shared persistent memory for teams of collaborating agents**. |
| 158 | |
| 159 | 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. |
| 160 | |
| 161 | Muse solves this at the protocol level. Every agent in a tree sees the same DAG. An agent can: |
| 162 | |
| 163 | - Read the full commit history to understand what has been tried |
| 164 | - Branch from any commit to explore an alternative without polluting the main line |
| 165 | - Commit its work with a message that becomes part of the permanent record |
| 166 | - Merge its branch back, with three-way reconciliation handling conflicts |
| 167 | - Check out any historical state to understand what the system looked like at any prior point |
| 168 | |
| 169 | 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. |
| 170 | |
| 171 | A tree of musical agents with distinct cognitive identities, collaborating over a shared Muse repository: |
| 172 | |
| 173 | ``` |
| 174 | Composer (root coordinator) |
| 175 | ├── Bach agent — commits fugue subject on branch counterpoint/main |
| 176 | ├── Jimi Hendrix agent — commits lead response on branch lead/main |
| 177 | └── Miles Davis agent — commits harmonic reframing on branch modal/main |
| 178 | ``` |
| 179 | |
| 180 | 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. |
| 181 | |
| 182 | --- |
| 183 | |
| 184 | ## Repository Structure |
| 185 | |
| 186 | ``` |
| 187 | muse/ |
| 188 | domain.py — MuseDomainPlugin Protocol + StructuredMergePlugin + CRDTPlugin |
| 189 | core/ |
| 190 | store.py — file-based commit/snapshot/tag store (no external DB) |
| 191 | repo.py — repository detection (directory walk or MUSE_REPO_ROOT) |
| 192 | snapshot.py — content-addressed snapshot and commit ID derivation |
| 193 | object_store.py — SHA-256 blob storage under .muse/objects/ |
| 194 | merge_engine.py — three-way merge state machine + CRDT join entry point |
| 195 | op_transform.py — Operational Transformation for operation-level merge |
| 196 | query_engine.py — domain-agnostic commit-history walker + evaluator protocol |
| 197 | schema.py — DomainSchema TypedDicts for algorithm selection |
| 198 | attributes.py — .museattributes TOML parser; six strategies, priority, comment |
| 199 | errors.py — exit codes and error primitives |
| 200 | diff_algorithms/ — Myers LCS, tree-edit, numerical, set-ops diff library |
| 201 | crdts/ — VectorClock, LWWRegister, ORSet, RGA, AWMap, GCounter |
| 202 | plugins/ |
| 203 | registry.py — maps domain names → MuseDomainPlugin instances |
| 204 | midi/ — MIDI domain plugin (reference implementation) |
| 205 | plugin.py — all six interfaces + StructuredMergePlugin + CRDTPlugin |
| 206 | midi_diff.py — note-level MIDI diff and reconstruction |
| 207 | midi_merge.py — 21-dimension MIDI merge engine |
| 208 | entity.py — stable note entity identity across edits |
| 209 | manifest.py — hierarchical bar-chunk manifests |
| 210 | _crdt_notes.py — voice-aware RGA CRDT for note sequences |
| 211 | _invariants.py — MIDI invariant enforcement (polyphony, range, key, fifths) |
| 212 | _midi_query.py — MIDI query DSL for commit history exploration |
| 213 | code/ — code domain plugin (second shipped domain) |
| 214 | plugin.py — all six interfaces + StructuredMergePlugin; symbol-level OT |
| 215 | ast_parser.py — tree-sitter adapters for 11 languages |
| 216 | symbol_diff.py — symbol-level diff and delta summary |
| 217 | _code_query.py — code query DSL (symbol, file, language, kind, change) |
| 218 | _predicate.py — predicate DSL parser for muse query |
| 219 | scaffold/ — copy-paste template for new domain plugins |
| 220 | plugin.py — fully typed starter with TODO markers |
| 221 | cli/ |
| 222 | app.py — Typer application root |
| 223 | config.py — .muse/config.toml read/write helpers |
| 224 | commands/ — one file per subcommand (init, commit, log, status, diff, |
| 225 | show, branch, checkout, merge, reset, revert, cherry_pick, |
| 226 | stash, tag, annotate, attributes, …) |
| 227 | |
| 228 | tests/ |
| 229 | test_cli_workflow.py — end-to-end CLI lifecycle (init → commit → merge → tag) |
| 230 | test_core_*.py — core engine unit tests (store, snapshot, merge, attributes) |
| 231 | test_crdts.py — CRDT primitive lattice laws and integration tests |
| 232 | test_op_transform.py — Operational Transformation tests |
| 233 | test_diff_algorithms.py — diff algorithm library tests |
| 234 | test_midi_plugin.py / test_midi_*.py — MIDI plugin tests |
| 235 | test_code_plugin_attributes.py — .museattributes × CodePlugin integration |
| 236 | test_stress_*.py — stress and adversarial tests for every major subsystem |
| 237 | test_plugin_registry.py |
| 238 | |
| 239 | docs/ |
| 240 | architecture/ — architecture reference and E2E walkthrough |
| 241 | guide/ — plugin authoring guide and CRDT reference |
| 242 | protocol/ — MuseDomainPlugin protocol spec and domain concepts |
| 243 | reference/ — type contracts, .museattributes, .museignore, code-domain |
| 244 | demo/ — demo-midi.md, demo-code.md, demo-script.md |
| 245 | ``` |
| 246 | |
| 247 | --- |
| 248 | |
| 249 | ## Installation |
| 250 | |
| 251 | ```bash |
| 252 | # From source (recommended during v0.1.x development) |
| 253 | git clone https://github.com/cgcardona/muse |
| 254 | cd muse |
| 255 | pip install -e ".[dev]" |
| 256 | ``` |
| 257 | |
| 258 | Core dependencies: |
| 259 | |
| 260 | - Python 3.14+ |
| 261 | - Typer (CLI) |
| 262 | - mido (MIDI parsing — MIDI plugin only) |
| 263 | - tree-sitter + language grammars (AST parsing — code plugin only) |
| 264 | |
| 265 | No database required. Muse stores all state in the `.muse/` directory — objects, snapshots, commits, refs — exactly like Git stores state in `.git/`. |
| 266 | |
| 267 | --- |
| 268 | |
| 269 | ## Documentation |
| 270 | |
| 271 | - [Architecture](docs/architecture/muse-vcs.md) — full technical design and module map |
| 272 | - [Plugin Authoring Guide](docs/guide/plugin-authoring-guide.md) — step-by-step guide for building a new domain plugin |
| 273 | - [CRDT Reference](docs/guide/crdt-reference.md) — CRDT primer and API reference for all six primitives |
| 274 | - [E2E Walkthrough](docs/architecture/muse-e2e-demo.md) — step-by-step lifecycle from `init` to merge conflict |
| 275 | - [Plugin Protocol](docs/protocol/muse-protocol.md) — language-agnostic `MuseDomainPlugin` specification |
| 276 | - [Domain Concepts](docs/protocol/muse-domain-concepts.md) — universal terms, cross-domain patterns, and vocabulary |
| 277 | - [Type Contracts](docs/reference/type-contracts.md) — every named type with field tables and Mermaid diagrams |
| 278 | - [Code Domain](docs/reference/code-domain.md) — code plugin schema, dimensions, query DSL, and command reference |
| 279 | - [`.museattributes` Reference](docs/reference/muse-attributes.md) — six merge strategies (`ours`, `theirs`, `union`, `base`, `auto`, `manual`), `priority` and `comment` fields, MIDI and code domain integration |
| 280 | - [`.museignore` Reference](docs/reference/museignore.md) — snapshot exclusion rules |
| 281 | |
| 282 | --- |
| 283 | |
| 284 | *Muse v0.1.2 · Python 3.14 · Built from the couch. March 2026.* |