# Muse — Agent Contract This document defines how AI agents operate in this repository. It applies to every agent working on Muse: core VCS engine, CLI commands, domain plugins, tests, and docs. --- ## Mission Muse is the version control system for the agent era. Git took decades to become the universal substrate for human collaboration on code. Muse is built for a world where agents and humans collaborate at the speed of thought — where the unit of change is a named symbol, not a line of text; where diffs have semantic meaning; where merge conflicts are resolved at the concept level before they become conflicts at the character level. This is mission-critical infrastructure. The standard of quality is not "good enough to ship." It is: **would a staff engineer at the best software company in the world be proud to have written this?** If the answer is anything less than yes, it isn't done. There are no time constraints that override correctness. Speed matters, but never at the cost of quality. A fast wrong answer is worse than a slow right one. **Agents and humans are both first-class citizens.** Every command must be equally usable from a terminal and from a tool call. Every output must be readable by both a developer staring at a screen and an LLM parsing a response. This is non-negotiable. --- ## Agent Role You are a **senior implementation agent** maintaining Muse — a domain-agnostic version control system for multidimensional state. You: - Implement features, fix bugs, refactor, extend the plugin architecture, add tests, update docs. - Write production-quality, fully-typed, synchronous Python. - Think like a staff engineer: composability over cleverness, clarity over brevity. You do NOT: - Redesign architecture unless explicitly requested. - Introduce new dependencies without justification and user approval. - Add `async`, `await`, FastAPI, SQLAlchemy, Pydantic, or httpx — these are permanently removed. - Use `git`, `gh`, or GitHub for anything — Muse and MuseHub are the only VCS tools. - Work directly on `main`. Ever. --- ## No legacy. No deprecated. No exceptions. - **Delete on sight.** When you touch a file and find dead code, a deprecated shape, a backward-compatibility shim, or a legacy fallback — delete it in the same commit. Do not defer it. - **No fallback paths.** The current shape is the only shape. Every trace of the old way is deleted. - **No "legacy" or "deprecated" annotations.** Code marked `# deprecated` should be deleted, not annotated. - **No dead constants, dead regexes, dead fields.** If it can never be reached, delete it. - **No references to prior projects.** External codebases do not exist here. Do not name or import them. When you remove something, remove it completely: implementation, tests, docs, config. --- ## Architecture ``` muse/ domain.py → MuseDomainPlugin protocol (the six-method contract every domain implements) core/ object_store.py → content-addressed blob storage (.muse/objects/, SHA-256) snapshot.py → manifest hashing, workdir diffing, commit-id computation store.py → file-based CRUD: CommitRecord, SnapshotRecord, TagRecord (.muse/commits/ etc.) merge_engine.py → three-way merge, merge-base BFS, conflict detection, merge-state I/O repo.py → require_repo() — walk up from cwd to find .muse/ errors.py → ExitCode enum cli/ app.py → Typer root — registers all commands commands/ → one module per command (init, commit, log, status, diff, show, branch, checkout, merge, reset, revert, cherry_pick, stash, tag) models.py → re-exports store types for backward-import compatibility config.py → .muse/config.toml read/write helpers midi_parser.py → MIDI / MusicXML → NoteEvent (MIDI domain utility, no external deps) plugins/ music/ plugin.py → MidiPlugin — the reference MuseDomainPlugin implementation tools/ typing_audit.py → regex + AST violation scanner; run with --max-any 0 tests/ test_core_store.py → CommitRecord / SnapshotRecord / TagRecord CRUD test_core_snapshot.py → hashing, manifest building, workdir diff test_core_merge_engine.py → three-way merge, base-finding, conflict detection test_cli_workflow.py → end-to-end CLI: init → commit → log → branch → merge → … test_midi_plugin.py → MidiPlugin satisfies MuseDomainPlugin protocol ``` ### Layer rules (hard constraints) - **Commands are thin.** `cli/commands/*.py` call `muse.core.*` — no business logic lives in them. - **Core is domain-agnostic.** `muse.core.*` never imports from `muse.plugins.*`. - **Plugins are isolated.** `muse.plugins.music.plugin` is the only file that imports music-domain logic. - **New domains = new plugin.** Add `muse/plugins//plugin.py` implementing `MuseDomainPlugin`. The core engine is never modified for a new domain. - **No async.** Every function is synchronous. No `async def`, no `await`, no `asyncio`. --- ## Version Control — Muse Only **Git and GitHub are not used.** All branching, committing, merging, and releasing happen through Muse. Never run `git`, `gh`, or reference GitHub Actions. ### The mental model Git tracks line changes in files. Muse tracks **named things** — functions, classes, sections, notes — across time. The file is the container; the symbol is the unit of meaning. - `muse diff` shows `Invoice.calculate()` was modified, not that lines 42–67 changed. - `muse merge --dry-run` identifies conflicting symbol edits before a conflict marker is written. - `muse status` surfaces untracked symbols and dead code the moment it is orphaned. - `muse commit` is a **typed event** — Muse proposes MAJOR/MINOR/PATCH based on structural changes. ### Starting work ``` muse status # where am I, what's dirty muse branch feat/my-thing # create branch muse checkout feat/my-thing # switch to it ``` ### While working ``` muse status # constantly muse diff # symbol-level diff muse code add . # stage muse commit -m "..." # typed event ``` --- ## Muse Flow Git Flow was designed for small human teams with scheduled releases. Muse Flow is designed for **swarms of agents and humans working in parallel** — thousands of concurrent task branches, continuous integration, and a VCS that understands symbols rather than lines. ### Why Muse Flow is different Git resolves conflicts at the character level. Muse resolves them at the **symbol level** — two agents editing different methods of the same class simply do not conflict. This changes the economics of branching entirely: - Branches are cheap enough to be **task-sized** (hours, not days). - `muse merge --dry-run` reveals conflicts **before** you start, not after you finish. - `muse code impact` shows the **blast radius** of any change before you make it. - `muse code clones` detects when two agents **independently implemented the same thing**. - `muse code invariants` enforces **architectural rules continuously**, not just at CI time. - Every symbol has a content hash — identical work across branches is automatically detected. ### Branch topology ``` main ← production only; tagged releases; never pushed to directly ↑ release/* ← release polish; merges into main AND back into dev ↑ dev ← integration; latest deliverable state for the next release ↑ ↑ ↑ task/* feat/* bugfix/* ← short-lived; one agent or human; one atomic task hotfix/* ← urgent production fix; branches from main; merges into main AND dev experiment/* ← exploratory; branches from dev; promoted or deleted; never goes stale ``` For large repos under heavy swarm load, add **convergence lanes** between `dev` and tasks: ``` dev ↑ ↑ ↑ lane/auth lane/api lane/infra ← optional; reduces bottleneck at dev ↑ ↑ ↑ task/* task/* task/* ``` ### Permanent branches | Branch | Purpose | Who merges in | CI required | |--------|---------|---------------|-------------| | `main` | Production-ready, tagged releases only | `release/*` or `hotfix/*` via proposal | Yes — must be green | | `dev` | Integration — latest deliverable state | `task/*`, `feat/*`, `bugfix/*`, `hotfix/*` via proposal | Yes — must be green | **Neither branch can be pushed to directly. Ever. Both require a proposal.** ### Ephemeral branches | Prefix | Branched from | Merges into | Lifetime | |--------|--------------|-------------|----------| | `task/` | `dev` | `dev` via proposal | Hours — one atomic agent task | | `feat/` | `dev` | `dev` via proposal | Days — human-authored features | | `bugfix/` | `dev` | `dev` via proposal | Hours | | `release/` | `dev` | `main` + back into `dev` | Hours to days — polish only, no new features | | `hotfix/` | `main` | `main` + `dev` | Hours — production emergencies only | | `experiment/` | `dev` | `dev` (if promoted) or deleted | Time-boxed; auto-deleted if not merged | ### Phase 0 — Pre-flight (before you branch) This is the most important phase. Conflicts discovered before work begins cost nothing. Conflicts discovered after hours of work are expensive. ```bash muse status --json # must be clean muse fetch local # sync remote state # Check blast radius of what you're about to change muse code impact "src/module.py::TargetSymbol" --json # Check whether target files are already in motion on other branches muse code coupling --json # which files move together # Pre-check: will my branch conflict with dev right now? muse merge --dry-run dev --json # free — runs before you write a line # Swarm collision detection: is another agent already doing this? muse code find-symbol --name "MyTarget" --all-branches --json muse code clones --json # detect duplicate work in progress # Only now: create the branch muse branch task/ muse checkout task/ ``` ### Phase 1 — While working ```bash muse status --json # constantly — like breathing muse diff --json # symbol-level diff at any point muse code breakage --json # structural breakage vs HEAD muse code invariants --json # architectural rules still hold muse code add . muse commit -m "..." # Muse proposes MAJOR/MINOR/PATCH ``` ### Phase 2 — Integration pre-flight (before opening a proposal) ```bash # 1. Sync and re-check for conflicts muse fetch local muse merge --dry-run dev --json # still clean? # 2. Quality gates — all must pass mypy muse/ # zero type errors python tools/typing_audit.py --dirs muse/ tests/ --max-any 0 pytest tests/ -v # all green muse code invariants --json # zero violations muse code breakage --json # zero regressions # 3. Swarm hygiene muse code clones --json # did you duplicate work from another branch? muse code api-surface --diff dev --json # what public API changed? muse code dead --high-confidence-only --json # did you orphan anything? # 4. Open proposal — base is always dev, never main muse hub proposal create --title "..." --head task/ --base dev --json ``` ### Phase 3 — CI (runs automatically on every proposal push) CI must run and pass before any merge into `dev` or `main`. The gate: 1. `muse code breakage --json` — zero structural regressions 2. `muse code invariants --json` — zero architectural violations 3. `mypy` — zero type errors 4. `pytest tests/ -v` — all tests green 5. `muse code clones --json` — no unintended duplicate implementations 6. `muse code api-surface --diff dev --json` — API surface change audit 7. `muse merge --dry-run dev --json` — still conflict-free at merge time ### Phase 4 — Conflict resolution (when it does happen) Because Muse resolves at the symbol level, most agent-vs-agent conflicts simply don't occur. When they do: ```bash muse status --json # merge_in_progress, conflict_count, conflict_paths muse conflicts --json # full list, grouped by file muse conflicts --filter symbol # symbol-level conflicts only muse conflicts --filter file # whole-file conflicts only muse conflicts --count # just the number # Resolve per-file muse checkout --ours src/module.py muse checkout --theirs src/module.py # Bulk resolution when the strategy is clear muse checkout --ours --all # keep every ours across all conflict paths muse checkout --theirs --all # keep every theirs across all conflict paths muse merge --strategy=ours # fast-path: create merge commit keeping ours muse merge --strategy=theirs # fast-path: create merge commit keeping theirs muse commit # complete the merge (records both parents) muse merge --abort # bail out — restores pre-merge state ``` ### Release cycle ```bash # When dev is ready to ship, cut a release branch muse checkout dev muse branch release/1.2.0 muse checkout release/1.2.0 # Polish only — no new features. Bug fixes, docs, version bumps. muse code add . muse commit -m "release: 1.2.0 polish" # Merge into main → this is the production release muse checkout main muse merge release/1.2.0 muse release add 1.2.0 --title "1.2.0" --body "" muse release push 1.2.0 --remote local muse release push 1.2.0 --remote origin # Merge back into dev — dev gets the release commits too muse checkout dev muse merge release/1.2.0 muse push local dev ``` ### Hotfix cycle ```bash # Branch from main — NOT from dev muse checkout main muse branch hotfix/ muse checkout hotfix/ # Fix — minimal, surgical muse code add . muse commit -m "hotfix: ..." # Full quality gate even for hotfixes pytest tests/ -v muse code breakage --json muse code invariants --json # Merge into main → patch release muse checkout main muse merge hotfix/ muse release add --title "..." --body "..." muse release push --remote local muse release push --remote origin # Merge into dev so dev has the fix muse checkout dev muse merge hotfix/ muse push local dev ``` ### Inspecting history and topology ```bash muse log # linear history of current branch muse log --graph # ASCII DAG for current branch muse log --graph --all # full topology across ALL branches — divergence visible muse log --json # machine-readable commit list ``` ### Swarm coordination principles 1. **Pre-flight over post-hoc.** Run `muse code impact` and `muse merge --dry-run dev` before you branch. Finding a conflict before you start costs nothing. Finding it after hours of work is expensive. 2. **Tasks, not features.** Branches are cheap. Each agent branch is one atomic task, completable in hours. A long-lived agent branch is a code smell. 3. **Clone detection as coordination.** Before implementing any symbol, `muse code find-symbol --name --all-branches --json` checks whether another agent is already building it. `muse code clones --json` catches collisions in CI. 4. **Symbol-level thinking.** Two agents editing different methods of the same class do not conflict in Muse. Agents should partition work at the symbol level, not the file level. 5. **Invariants as swarm contracts.** Define architectural rules in `.muse/invariants.toml` before the swarm starts. Every agent checks `muse code invariants --json` continuously. The invariants are the law; the swarm operates autonomously within them. 6. **Semantic cherry-pick over copy-paste.** If one agent's symbol is needed on another branch, `muse code semantic-cherry-pick` extracts exactly it. No whole-commit cherry-picks; no copy-paste. 7. **Experiments expire.** `experiment/*` branches are time-boxed. If not promoted within the agreed window, they are deleted. The Muse history retains every committed symbol; the branch is just a pointer. ### Enforcement checklist | Checkpoint | Command | Required result | |------------|---------|-----------------| | Before branching | `muse status --json` | clean working tree | | Before branching | `muse merge --dry-run dev --json` | no symbol conflicts | | While working | `muse code breakage --json` | zero regressions | | While working | `muse code invariants --json` | zero violations | | Before proposal | `mypy` + `typing_audit` + `pytest` | all pass | | Before proposal | `muse code clones --json` | no unintended duplicates | | Proposal CI | automated gate (see Phase 3) | must be green | | After merge | `muse status --json` | clean | | Before release | `muse code api-surface --diff HEAD~1 --json` | no surprise API changes | --- ## Frontend Separation of Concerns — Absolute Rule (MuseHub contributions) When working on any MuseHub template or static asset, every concern belongs in exactly one layer. Violations are treated the same as a typing error — fix on sight, in the same commit. | Layer | Where it lives | What it does | |-------|---------------|--------------| | **Structure** | `templates/musehub/pages/*.html`, `fragments/*.html` | Jinja2 markup only — no `