# Code Domain — Complete Reference > **Engine:** `muse/plugins/code/` · **No external deps for core analysis** > **Scope:** Every command, module, type, and protocol in the code domain plugin --- ## Overview The code domain plugin treats a codebase as a **typed, content-addressed symbol graph** — not as a bag of text lines. Every function, class, method, variable, and import becomes a `SymbolRecord` with a stable content-addressed identity (SHA-256). This unlocks operations that are structurally impossible in Git: - Track a function through renames and cross-file moves with perfect identity. - Cherry-pick a single named function out of a historical commit. - Detect exact and near-duplicate code across an entire snapshot in O(1). - Predict merge conflicts before writing a single byte. - Enforce architectural invariants as committed rules. - Assign semantic version bumps automatically at commit time. - Coordinate thousands of parallel agents without a central lock server. --- ## Contents 1. [Selective Staging (`muse code add`)](#1-selective-staging-muse-code-add) 2. [Symbol Identity Model](#2-symbol-identity-model) 3. [Provenance & Topology Commands](#3-provenance--topology-commands) 4. [Query & Temporal Search](#4-query--temporal-search) 5. [Index Infrastructure](#5-index-infrastructure) 6. [Symbol Identity Detail](#6-symbol-identity-detail) 7. [Multi-Agent Coordination Layer](#7-multi-agent-coordination-layer) 8. [Merge Engine & Architectural Enforcement](#8-merge-engine--architectural-enforcement) 9. [Semantic Versioning](#9-semantic-versioning) 10. [Call-Graph Tier Commands](#10-call-graph-tier-commands) 11. [Architecture Internals](#11-architecture-internals) 12. [Type Reference](#12-type-reference) --- ## 1. Selective Staging (`muse code add`) The code domain adds a **Git-style staging index** to Muse. By default, `muse commit` snapshots the entire working tree. Once you run `muse code add`, the next commit includes *only* what you have explicitly staged — everything else carries forward from the previous commit unchanged. This lets you commit a coherent, working subset of your in-progress changes without committing half-finished code. ### Stage index location `.muse/code/stage.json` — a JSON file that maps workspace-relative paths to their staged object IDs and mode (`A` added / `M` modified / `D` deleted`). ### `muse code add` ``` muse code add [ …] # stage one or more files muse code add # stage every file under a directory muse code add . # stage everything in the working tree muse code add -A / --all # stage all changes, including new files muse code add -u / --update # stage only tracked (already-committed) files # modified or deleted on disk — no new files muse code add -p / --patch # interactive hunk-by-hunk staging muse code add -n / --dry-run … # show what would be staged without staging muse code add -v / --verbose … # print each file as it is staged ``` #### Patch mode (`-p`) Interactive hunk-by-hunk staging, mirroring `git add -p`. For each diff hunk you are prompted: | Key | Action | |-----|--------| | `y` | Stage this hunk | | `n` | Skip this hunk | | `q` | Quit; commit hunks accepted so far | | `a` | Stage this and all remaining hunks in this file | | `d` | Skip the rest of this file | | `?` | Show help | The partial file (accepted hunks only) is hashed, written to the object store, and recorded in the stage index. The working tree is **never modified**. Agents should use explicit file paths (`muse code add `) and avoid `--patch`, which requires an interactive terminal. ### `muse code reset` ``` muse code reset # unstage everything muse code reset # unstage a specific file muse code reset HEAD # same — mirrors Git syntax ``` Removes files from the stage index without touching the working tree. The working tree copy is always preserved. ### `muse commit` with an active stage When `.muse/code/stage.json` exists and is non-empty: - Staged files → committed at their **staged** object ID. - Tracked-but-unstaged files → carried forward at their **committed** (HEAD) object ID. - Untracked files → not included in the commit. After a successful commit the stage index is **cleared automatically**. ### `muse status` with an active stage When a stage is active, `muse status` renders a three-bucket view: ``` On branch main Changes staged for commit: (use "muse code reset HEAD " to unstage) new file: src/auth.py modified: src/models.py Changes not staged for commit: (use "muse code add " to update what will be committed) modified: src/broken_wip.py Untracked files: (use "muse code add " to include in what will be committed) tmp_experiment.py ``` With `--format json`: ```json { "branch": "main", "clean": false, "staged": { "src/auth.py": {"mode": "A", "object_id": ""} }, "unstaged": { "src/broken_wip.py": "modified" }, "untracked": ["tmp_experiment.py"] } ``` ### Workflow example ```bash # Edit freely — nothing is committed until you stage. vim src/auth.py src/models.py src/wip.py # Stage only the production-ready files. muse code add src/auth.py src/models.py # Verify what will be committed. muse status # Commit exactly what was staged. muse commit -m "feat: add auth + models" # The working-tree copy of wip.py is untouched. ``` --- ## 2. Symbol Identity Model Every symbol carries four content-addressed hashes and two stable keys: | Field | Description | |---|---| | `content_id` | SHA-256 of the full normalized AST (signature + body + metadata). Two symbols are identical iff their `content_id` matches. | | `body_hash` | SHA-256 of the function/class body only (excluding signature and decorators). Matches across renames and decorator changes. | | `signature_id` | SHA-256 of the normalized parameter list and return annotation. Matches across implementation-only changes. | | `metadata_id` *(v2)* | SHA-256 of decorator list + async flag + base classes. Matches when only the implementation or signature changed. | | `canonical_key` *(v2)* | `{file}#{scope}#{kind}#{name}#{lineno}` — stable machine handle for agent-to-agent symbol handoff. | | `qualified_name` | Dotted path within the file (e.g. `MyClass.my_method`). | ### Exact Refactor Classification Two symbols are classified by comparing their four hashes: | Classification | Condition | |---|---| | `unchanged` | `content_id` matches | | `rename` | `body_hash` matches, name differs, same file | | `move` | `content_id` matches, different file, same name | | `rename+move` | `body_hash` matches, different file, different name | | `signature_only` | `body_hash` matches, `signature_id` differs | | `impl_only` | `signature_id` matches, `body_hash` differs | | `metadata_only` | `body_hash` + `signature_id` match, `metadata_id` differs | | `full_rewrite` | Both signature and body changed | --- ## 3. Provenance & Topology Commands ### `muse code lineage ADDRESS` Full provenance chain of a named symbol from its first appearance to the present. ``` muse code lineage src/billing.py::compute_total muse code lineage src/billing.py::compute_total --commit HEAD~10 muse code lineage src/billing.py::compute_total --json ``` **How it works:** Walks all commits in chronological order, scanning `InsertOp`/`DeleteOp`/`ReplaceOp` entries in each `structured_delta`. Rename detection uses `content_id` matching across Insert+Delete pairs within a single commit. **Output events:** `created`, `modified`, `renamed_from`, `moved_from`, `deleted`. **Flags:** - `--commit REF` — stop history walk at this commit (default: HEAD) - `--json` — emit a JSON array of event objects **JSON schema:** ```json [ { "event": "created", "commit_id": "a1b2c3d4...", "committed_at": "2026-01-01T00:00:00+00:00", "message": "Initial commit", "address": "src/billing.py::compute_total", "content_id": "sha256..." } ] ``` --- ### `muse code api-surface` Public API surface of a snapshot — every non-underscore function, class, and method. ``` muse code api-surface muse code api-surface --commit v1.0 muse code api-surface --diff v1.0 muse code api-surface --json ``` **With `--diff REF`:** Shows three sections — **Added** (new public symbols), **Removed** (deleted public symbols), **Changed** (same address, different `content_id`). **Public** means: `kind` in `{function, class, method, async_function}` and `name` not starting with `_`. --- ### `muse code codemap` Semantic topology of the entire codebase at a snapshot. ``` muse code codemap muse code codemap --top 10 muse code codemap --commit HEAD~5 muse code codemap --json ``` **What it shows:** - **Modules by size** — ranked by symbol count - **Import graph** — in-degree (how many modules import this one) - **Cycles** — import cycles detected via DFS (a hard architectural smell) - **High-centrality symbols** — functions called from many places (blast-radius risk) - **Boundary files** — high fan-out (imports many), zero fan-in (nothing imports them) **Flags:** - `--top N` — show top N entries per section (default: 5) - `--commit REF` — snapshot to analyse - `--json` — structured output --- ### `muse code clones` Find exact and near-duplicate symbol clusters across the snapshot. ``` muse code clones muse code clones --tier exact muse code clones --tier near muse code clones --tier both muse code clones --commit HEAD~3 --json ``` **Exact clones:** Same `body_hash` at different addresses. These are literal copy-paste duplicates — same implementation, possibly different name. **Near-clones:** Same `signature_id`, different `body_hash`. Same public contract (parameters + return type), diverged implementation — a maintainability risk. **Output:** Clusters, one per group, listing all member addresses. --- ### `muse code checkout-symbol ADDRESS --commit REF` Restore a single named symbol from a historical commit into the current working tree. Only the target symbol's lines change; everything else is untouched. ``` muse code checkout-symbol src/billing.py::compute_total --commit v1.0 muse code checkout-symbol src/billing.py::compute_total --commit abc123 --dry-run muse code checkout-symbol src/billing.py::compute_total --commit v1.0 --json ``` **Flags:** - `--commit REF` *(required)* — source commit - `--dry-run` — print the unified diff without writing - `--json` — emit result as JSON for agent consumption **JSON output:** ```json { "address": "src/billing.py::compute_total", "file": "src/billing.py", "restored_from": "abc12345", "dry_run": false } ``` **Safety:** Rejects the operation if the target file cannot be parsed (syntax error) or if the symbol no longer exists at the destination location and the file cannot be safely patched. **Security:** The file path component of ADDRESS is validated via `contain_path()` before any disk access. Paths that escape the repo root (e.g. `../../etc/passwd::foo`) are rejected with exit 1. --- ### `muse code semantic-cherry-pick ADDRESS... --from REF` Cherry-pick one or more named symbols from a historical commit. Applies each symbol patch to the working tree at the symbol's current location; appends at the end of the file if the symbol is not present in the current tree. ``` muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0 muse code semantic-cherry-pick src/billing.py::f1 src/billing.py::f2 --from abc123 muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0 --dry-run --json ``` **Flags:** - `--from REF` *(required)* — source commit - `--dry-run` — show what would change without writing - `--json` — structured output with per-symbol patch results **JSON output:** ```json { "from_commit": "abc12345", "dry_run": false, "results": [ {"address": "src/billing.py::compute_total", "status": "applied", "detail": "lines 10–25 → 12 lines", "old_lines": 16, "new_lines": 12} ], "applied": 1, "failed": 0, "already_current": 0 } ``` **Security:** Every file path extracted from ADDRESS arguments is validated via `contain_path()` before any disk I/O or directory creation. Paths that escape the repo root are recorded as `not_found` and the remaining symbols continue to be processed. --- ## 4. Query & Temporal Search ### `muse code query PREDICATE...` Symbol graph predicate DSL — SQL for your codebase. ``` muse code query kind=function language=Python muse code query "(kind=function OR kind=method) name^=_" muse code query "NOT kind=import file~=billing" muse code query kind=function name~=validate --all-commits muse code query hash=a3f2c9 --all-commits --first muse code query --commit v1.0 kind=class muse code query kind=function --json ``` #### Predicate Grammar (v2) ``` expr = or_expr or_expr = and_expr ( "OR" and_expr )* and_expr = not_expr ( and_expr )* # implicit AND not_expr = "NOT" primary | primary primary = "(" expr ")" | atom atom = KEY OP VALUE ``` #### Operators | Operator | Meaning | |---|---| | `=` | Exact match (case-insensitive for strings) | | `~=` | Contains substring | | `^=` | Starts with | | `$=` | Ends with | | `!=` | Not equal | | `>=` | Greater than or equal (lineno keys only) | | `<=` | Less than or equal (lineno keys only) | #### Keys | Key | Type | Description | |---|---|---| | `kind` | string | `function`, `class`, `method`, `variable`, `import`, … | | `language` | string | `Python`, `Go`, `Rust`, `TypeScript`, … | | `name` | string | Bare symbol name | | `qualified_name` | string | Dotted qualified name (e.g. `MyClass.save`) | | `file` | string | File path (relative to repo root) | | `hash` | string | `content_id` prefix (hex) | | `body_hash` | string | `body_hash` prefix | | `signature_id` | string | `signature_id` prefix | | `lineno_gt` | integer | Symbol starts *after* this line number | | `lineno_lt` | integer | Symbol starts *before* this line number | #### Flags | Flag | Description | |---|---| | `--commit REF` | Query a specific commit (mutually exclusive with `--all-commits`) | | `--all-commits` | Walk all commits, deduplicate by `content_id`, annotate first-seen commit | | `--first` | With `--all-commits`: keep only the first appearance of each unique body | | `--json` | JSON output with `schema_version: 2` wrapper | --- ### `muse code query-history PREDICATE... [--from REF] [--to REF]` Temporal symbol search — track matching symbols across a commit range. ``` muse code query-history kind=function language=Python muse code query-history name~=validate --from v1.0 --to HEAD muse code query-history kind=class --json ``` **Output:** For each matching symbol address, reports `first_seen`, `last_seen`, `commit_count` (how many commits touched it), and `change_count` (how many times its `content_id` changed). **JSON schema:** ```json { "schema_version": 2, "query": "kind=function language=Python", "from_ref": "v1.0", "to_ref": "HEAD", "results": [ { "address": "src/billing.py::compute_total", "first_seen": "commit_id...", "last_seen": "commit_id...", "commit_count": 12, "change_count": 3 } ] } ``` --- ## 5. Index Infrastructure ### `muse code index status` Show present/absent/corrupt status and entry counts for all local indexes. ``` muse code index status muse code index status --json ``` **Flags:** - `--json` — emit status array as JSON **JSON output:** ```json [ {"name": "symbol_history", "status": "present", "entries": 1024, "updated_at": "2026-03-21T12:00:00"}, {"name": "hash_occurrence", "status": "absent", "entries": 0, "updated_at": null} ] ``` ### `muse code index rebuild` Rebuild one or all indexes by walking the full commit history. ``` muse code index rebuild muse code index rebuild --json muse code index rebuild --index symbol_history muse code index rebuild --index hash_occurrence --verbose ``` **Flags:** - `--index NAME` — rebuild only this index (default: all) - `--verbose, -v` — show progress while building - `--json` — emit rebuild summary as JSON **JSON output:** ```json { "rebuilt": ["symbol_history", "hash_occurrence"], "symbol_history_addresses": 512, "symbol_history_events": 2048, "hash_occurrence_clusters": 31, "hash_occurrence_addresses": 87 } ``` ### Index Design Indexes live under `.muse/indices/` and are: - **Derived** — computed entirely from the commit history. - **Optional** — no command requires them for correctness; they only provide speed. - **Fully rebuildable** — `muse code index rebuild` reconstructs them from scratch in one pass. - **Versioned** — `schema_version` field for forward compatibility. #### `symbol_history` index Maps `symbol_address → list[HistoryEntry]` (chronological). Enables O(1) lineage lookups instead of O(commits × files) scans. #### `hash_occurrence` index Maps `body_hash → list[symbol_address]`. Enables O(1) clone detection and `muse code find-symbol hash=` queries. --- ## 6. Symbol Identity Detail ### New `SymbolRecord` fields `SymbolRecord` gains two backward-compatible fields (empty string `""` for pre-v2 records): **`metadata_id`** : SHA-256 of the symbol's *metadata wrapper* — decorators + async flag for Python functions, decorator list + base classes for Python classes. Allows distinguishing a decorator change from a body change. **`canonical_key`** : `{file}#{scope}#{kind}#{name}#{lineno}` — a stable, unique machine handle for a symbol within a snapshot. Enables agent-to-agent symbol handoff without re-querying. Disambiguates overloaded names and nested scopes. ### `muse code detect-refactor` (v2 output) With `--json`, emits `schema_version: 2` with a richer classification: ```json { "schema_version": 2, "from_commit": "abc...", "to_commit": "def...", "total": 3, "events": [ { "old_address": "src/billing.py::compute_total", "new_address": "src/billing.py::compute_invoice_total", "old_kind": "function", "new_kind": "function", "exact_classification": "rename", "inferred_refactor": "none", "confidence": 1.0, "evidence": ["body_hash matches a1b2c3d4"], "old_content_id": "ab12cd34", "new_content_id": "ef56gh78", "old_body_hash": "a1b2c3d4", "new_body_hash": "a1b2c3d4" } ] } ``` **`exact_classification`** values: `rename`, `move`, `rename+move`, `signature_only`, `impl_only`, `metadata_only`, `full_rewrite`, `unchanged`. **`inferred_refactor`** values: `extract`, `inline`, `split`, `merge`, `none`. --- ## 7. Multi-Agent Coordination Layer The coordination layer enables thousands of agents to work on the same codebase simultaneously without stepping on each other. It is **purely advisory** — the VCS engine never reads coordination data for correctness decisions. Agents that ignore it still produce correct commits. ### Storage Layout ``` .muse/coordination/ reservations/.json advisory symbol lease intents/.json declared operation before edit ``` All records are **write-once** (never mutated) and use TTL-based expiry. Expired records are kept for audit purposes but ignored by all commands. --- ### `muse coord reserve ADDRESS... [OPTIONS]` Announce intent to edit one or more symbol addresses. ``` muse coord reserve src/billing.py::compute_total muse coord reserve src/billing.py::f1 src/billing.py::f2 --run-id agent-007 --ttl 7200 muse coord reserve src/billing.py::compute_total --op rename muse coord reserve src/billing.py::compute_total --json ``` **Flags:** - `--run-id ID` — identifier for this agent/run (default: random UUID) - `--ttl SECONDS` — reservation expiry in seconds (default: 3600) - `--op OPERATION` — declared operation: `rename`, `move`, `extract`, `modify`, `delete` - `--json` — JSON output **Conflict detection:** Warns (but never blocks) if any of the requested addresses are already reserved by another active reservation. **Reservation schema (v1):** ```json { "schema_version": 1, "reservation_id": "", "run_id": "", "branch": "", "addresses": ["src/billing.py::compute_total"], "created_at": "2026-03-18T12:00:00+00:00", "expires_at": "2026-03-18T13:00:00+00:00", "operation": "rename" } ``` --- ### `muse coord intent ADDRESS... --op OPERATION [OPTIONS]` Declare a specific operation before executing it. More precise than a reservation; enables `muse coord forecast` to produce accurate conflict predictions. ``` muse coord intent src/billing.py::compute_total --op rename --detail "rename to compute_invoice_total" muse coord intent src/billing.py::compute_total --op modify --reservation-id ``` **Flags:** - `--op OPERATION` *(required)* — `rename`, `move`, `extract`, `modify`, `delete`, `refactor` - `--detail TEXT` — free-text description of the planned change - `--reservation-id UUID` — link to an existing reservation - `--run-id ID` — agent identifier - `--json` — JSON output **Intent schema (v1):** ```json { "schema_version": 1, "intent_id": "", "reservation_id": "", "run_id": "", "branch": "", "addresses": ["src/billing.py::compute_total"], "operation": "rename", "created_at": "2026-03-18T12:00:00+00:00", "detail": "rename to compute_invoice_total" } ``` --- ### `muse coord forecast [OPTIONS]` Predict merge conflicts from active reservations and intents — **before** writing any code. ``` muse coord forecast muse coord forecast --branch feature-x muse coord forecast --json ``` **Conflict types detected:** | Type | Confidence | Condition | |---|---|---| | `address_overlap` | 1.0 | Two reservations on the same symbol address | | `blast_radius_overlap` | 0.75 | Reservations on symbols that call each other (via call graph) | | `operation_conflict` | 0.9 | Two reservations declare incompatible operations (e.g. both `rename`) | **Flags:** - `--branch BRANCH` — restrict to reservations on this branch - `--json` — structured conflict list --- ### `muse coord plan-merge OURS THEIRS [OPTIONS]` Dry-run semantic merge plan — classify all symbol conflicts without writing anything. ``` muse coord plan-merge main feature-x muse coord plan-merge HEAD~5 HEAD --json ``` **Output:** Classifies each diverging symbol into one of: - `no_conflict` — diverged in disjoint symbols - `symbol_edit_overlap` — both sides modified the same symbol - `rename_edit` — one side renamed, the other modified - `delete_use` — one side deleted a symbol still used by the other **Flags:** - `--json` — structured output with full classification details --- ### `muse coord shard --agents N [OPTIONS]` Partition the codebase into N low-coupling work zones for parallel agent assignment. ``` muse coord shard --agents 4 muse coord shard --agents 8 --language Python muse coord shard --agents 4 --json ``` **Algorithm:** Builds the import graph, finds connected components, greedily merges small components into N balanced shards (by symbol count). Reports cross-shard edges as a coupling score (lower is better). **Flags:** - `--agents N` *(required)* — number of shards - `--language LANG` — restrict to files of this language - `--json` — shard assignments as JSON --- ### `muse coord reconcile [OPTIONS]` Recommend merge ordering and integration strategy from the current coordination state. ``` muse coord reconcile muse coord reconcile --json ``` **Output:** For each active branch with reservations, recommends: - **Merge order** — branches with fewer predicted conflicts should merge first - **Integration strategy** — `fast-forward`, `rebase`, or `manual` (when conflicts are predicted) - **Conflict hotspots** — addresses that appear in the most reservations --- ## 8. Merge Engine & Architectural Enforcement ### `ConflictRecord` — Structured Conflict Taxonomy `MergeResult` now carries `conflict_records: list[ConflictRecord]` alongside the existing `conflicts: list[str]`. Each `ConflictRecord` provides structured metadata for programmatic conflict handling: ```python @dataclass class ConflictRecord: path: str conflict_type: str = "file_level" # see taxonomy below ours_summary: str = "" theirs_summary: str = "" addresses: list[str] = field(default_factory=list) ``` **`conflict_type` taxonomy:** | Value | Meaning | |---|---| | `symbol_edit_overlap` | Both branches modified the same symbol | | `rename_edit` | One branch renamed, the other modified | | `move_edit` | One branch moved, the other modified | | `delete_use` | One branch deleted a symbol still used by the other | | `dependency_conflict` | Conflicting changes to interdependent symbols | | `file_level` | Legacy — no symbol-level information available | --- ### `muse code breakage` Detect symbol-level structural breakage in the current working tree vs HEAD. ``` muse code breakage muse code breakage --language Python muse code breakage --json ``` **Checks performed:** 1. **`stale_import`** — a `from X import Y` where `Y` no longer exists in the committed version of `X` (detected via symbol graph, not execution). 2. **`missing_interface_method`** — a class body is missing a method that exists in the HEAD snapshot's version of that class. **What it does NOT do:** Execute code, install packages, run mypy or a type checker, or access the network. Pure structural analysis. **JSON output:** ```json { "breakage_count": 2, "issues": [ { "issue_type": "stale_import", "file": "src/billing.py", "description": "imports compute_total from src/utils.py but compute_total was removed" } ] } ``` --- ### `muse code invariants` Enforce architectural rules declared in `.muse/invariants.toml`. ``` muse code invariants muse code invariants --commit HEAD~5 muse code invariants --json ``` **Rule types:** #### `no_cycles` ```toml [[rules]] type = "no_cycles" name = "no import cycles" ``` The import graph must be a DAG. Reports every cycle as a violation. #### `forbidden_dependency` ```toml [[rules]] type = "forbidden_dependency" name = "core must not import cli" source_pattern = "muse/core/" forbidden_pattern = "muse/cli/" ``` Files matching `source_pattern` must not import from files matching `forbidden_pattern`. #### `layer_boundary` ```toml [[rules]] type = "layer_boundary" name = "plugins must not import from cli" lower = "muse/plugins/" upper = "muse/cli/" ``` Files in `lower` must not import from files in `upper` (enforces layered architecture). #### `required_test` ```toml [[rules]] type = "required_test" name = "all billing functions must have tests" source_pattern = "src/billing.py" test_pattern = "tests/test_billing.py" ``` Every public function in `source_pattern` must have a corresponding test function in `test_pattern` (matched by bare name). **Bootstrapping:** If `.muse/invariants.toml` does not exist, `muse code invariants` creates it with a commented template and exits with a guided onboarding message. --- ## 9. Semantic Versioning Muse automatically assigns semantic version bumps at commit time based on the `StructuredDelta`. ### `SemVerBump` ```python SemVerBump = Literal["major", "minor", "patch", "none"] ``` ### Inference rules (`infer_sem_ver_bump`) | Change type | Bump | Breaking? | |---|---|---| | Delete a public symbol | `major` | yes — address added to `breaking_changes` | | Rename a public symbol | `major` | yes — old address added to `breaking_changes` | | `signature_only` change | `major` | yes — callers may break | | Insert a new public symbol | `minor` | no | | `impl_only` change (body only) | `patch` | no | | `metadata_only` change | `none` | no | | Formatting-only change | `none` | no | | Non-public symbol changes | `patch` or `none` | no | **Public** = name does not start with `_` and kind is `function`, `class`, `method`, or `async_function`. ### Storage Both `StructuredDelta` and `CommitRecord` carry: - `sem_ver_bump: SemVerBump` (default `"none"`) - `breaking_changes: list[str]` (default `[]`) These fields are backward-compatible — pre-v2 commits read as `"none"` / `[]`. ### `muse log` display When a commit's `sem_ver_bump` is non-`none`, long-form `muse log` output appends: ``` SemVer: MAJOR Breaking: src/billing.py::compute_total, src/billing.py::Invoice (+2 more) ``` --- ## 10. Call-Graph Tier Commands ### `muse code impact ADDRESS [OPTIONS]` Transitive blast-radius analysis — what else breaks if this function changes? ``` muse code impact src/billing.py::compute_total muse code impact src/billing.py::compute_total --commit HEAD~5 muse code impact src/billing.py::compute_total --json ``` **Algorithm:** BFS over the reverse call graph (Python only via `ast`). Traverses until the transitive closure is exhausted, annotating each affected symbol with its depth. **Risk levels:** 🟢 (0–2 callers), 🟡 (3–9 callers), 🔴 (10+ callers). --- ### `muse code dead [OPTIONS]` Dead code detection — symbols with no callers and no importers. ``` muse code dead muse code dead --kind function muse code dead --exclude-tests muse code dead --json ``` **Detection logic:** A symbol is a dead-code candidate when: 1. Its bare name appears in no `ast.Call` node in the snapshot **and** 2. Its module is not imported anywhere in the snapshot. **Distinction:** `definite_dead` (module never imported) vs `soft_dead` (module imported but function never called directly). --- ### `muse code coverage CLASS_ADDRESS [OPTIONS]` Class interface call-coverage — which methods of a class are actually called? ``` muse code coverage src/billing.py::Invoice muse code coverage src/billing.py::Invoice --show-callers muse code coverage src/billing.py::Invoice --json ``` **Output:** Lists every method of the class, marks which ones appear in `ast.Call` nodes anywhere in the snapshot, and prints a coverage percentage. No test suite required. --- ### `muse code deps ADDRESS_OR_FILE [OPTIONS]` Import graph + call-graph analysis. ``` muse code deps src/billing.py muse code deps src/billing.py --reverse muse code deps src/billing.py::compute_total muse code deps src/billing.py::compute_total --reverse muse code deps src/billing.py --commit v1.0 --json ``` **File mode:** Lists all `import`-kind symbols from the file (what does it import?). With `--reverse`: which other files import this one. **Symbol mode** (`address` contains `::`): Python-only call extraction — which functions does this function call? With `--reverse`: which functions call this one. --- ### `muse code find-symbol [OPTIONS]` Cross-commit, cross-branch symbol search by hash, name, or kind. ``` muse code find-symbol --hash a3f2c9 muse code find-symbol --name compute_total muse code find-symbol --name compute_* --kind function muse code find-symbol --hash a3f2c9 --all-branches --first muse code find-symbol --name validate --json ``` **Flags:** - `--hash HEX` — match `content_id` prefix (exact body match across history) - `--name NAME` — exact name or prefix glob with `*` - `--kind KIND` — restrict to symbol kind - `--all-branches` — also scan all branch tips in `.muse/refs/heads/` - `--first` — deduplicate on `content_id`, keeping only the first appearance - `--json` — structured output --- ### `muse code patch ADDRESS SOURCE [OPTIONS]` Surgical semantic patch — replace exactly one named symbol in the working tree. ``` muse code patch src/billing.py::compute_total new_impl.py echo "def compute_total(x): return x * 2" | muse code patch src/billing.py::compute_total - muse code patch src/billing.py::compute_total new_impl.py --dry-run muse code patch src/billing.py::compute_total new_impl.py --json ``` **Syntax validation:** Before writing, validates the replacement source with: - `ast.parse` for Python - `tree-sitter` CST error-node check for all 11 supported languages Rejects the patch and exits non-zero if the source has syntax errors. **Flags:** - `--body, -b FILE` *(required)* — file containing the replacement source (`-` for stdin) - `--dry-run, -n` — print what would change without writing - `--json` — emit result as JSON for agent consumption **JSON output:** ```json { "address": "src/billing.py::compute_total", "file": "src/billing.py", "lines_replaced": 12, "new_lines": 9, "dry_run": false } ``` **Security:** The file path component of ADDRESS is validated via `contain_path()` before any disk access. Paths that escape the repo root (e.g. `../../etc/passwd::foo`) are rejected with exit 1. --- ### `muse grep PATTERN [OPTIONS]` Search the typed symbol graph by name — not file text. Every result is a real symbol declaration; no false positives from comments, string literals, or call sites. ``` muse grep validate muse grep "^handle" --regex muse grep Invoice --kind class muse grep compute --language Go muse grep total --commit HEAD~5 muse grep validate --json ``` **Flags:** | Flag | Short | Description | |---|---|---| | `--regex, -e` | | Treat PATTERN as a Python regex (default: substring match) | | `--kind KIND, -k` | | Restrict to symbols of this kind (function, class, method, …) | | `--language LANG, -l` | | Restrict to files of this language (Python, Go, …) | | `--commit REF, -c` | | Search a historical commit instead of HEAD | | `--hashes` | | Include 8-char content-ID prefix in output | | `--json` | | Emit results as JSON | **JSON output:** ```json [ { "address": "src/auth.py::validate_token", "kind": "function", "name": "validate_token", "qualified_name": "validate_token", "file": "src/auth.py", "lineno": 14, "language": "Python", "content_id": "cb4afa1234567890..." } ] ``` **Security:** Patterns are capped at 512 characters to prevent ReDoS. Invalid regex syntax is caught and reported as exit 1 rather than crashing. --- ### `muse code-check [COMMIT] [OPTIONS]` Enforce semantic code invariants against a commit snapshot. ``` muse code-check # check HEAD muse code-check abc1234 # check specific commit muse code-check --strict # exit 1 on any error-severity violation muse code-check --json # machine-readable JSON output muse code-check --rules my_rules.toml # custom rules file inside the repo ``` **Flags:** | Flag | Description | |---|---| | `COMMIT` | Commit ID to check (default: HEAD) | | `--strict` | Exit 1 when any error-severity violation is found | | `--json` | Emit machine-readable JSON | | `--rules FILE` | Path to a TOML invariants file **inside the repo** (default: `.muse/code_invariants.toml`) | **Security:** `--rules FILE` is validated via `contain_path()` — paths that escape the repo root are rejected with exit 1. --- ## 11. Architecture Internals ### Module Map ``` muse/ plugins/code/ plugin.py MidiPlugin → CodePlugin (MuseDomainPlugin + StructuredMergePlugin) ast_parser.py Python AST → SymbolRecord; validate_syntax() for all 11 languages symbol_diff.py diff_symbol_trees() — O(n) diffing, rename/move annotation _query.py symbols_for_snapshot(), walk_commits(), language_of() _predicate.py Predicate DSL parser — tokenise → recursive descent → Predicate callable _callgraph.py ForwardGraph, ReverseGraph, build_*, transitive_callers BFS _refactor_classify.py classify_exact(), classify_composite(), RefactorClassification core/ coordination.py Reservation, Intent, create/load helpers, .muse/coordination/ indices.py SymbolHistoryIndex, HashOccurrenceIndex, save/load/rebuild ``` ### Language Support | Language | Extension(s) | Parser | Symbol types | |---|---|---|---| | Python | `.py` | `ast` (stdlib) | function, async_function, class, method, variable, import | | JavaScript | `.js` `.jsx` `.mjs` `.cjs` | tree-sitter | function, class, method | | TypeScript | `.ts` `.tsx` | tree-sitter | function, class, method, interface, type_alias, enum | | Go | `.go` | tree-sitter | function (method qualified as `Type.Method`) | | Rust | `.rs` | tree-sitter | function (impl method qualified as `Type.method`) | | Java | `.java` | tree-sitter | class, interface, method, constructor, enum | | C | `.c` `.h` | tree-sitter | function_definition | | C++ | `.cpp` `.cc` `.cxx` `.hpp` | tree-sitter | function, class, struct | | C# | `.cs` | tree-sitter | class, interface, struct, method, constructor, enum | | Ruby | `.rb` | tree-sitter | class, module, method, singleton_method | | Kotlin | `.kt` `.kts` | tree-sitter | function, class, method | ### Layer Rules - `muse/core/*` is domain-agnostic — never imports from `muse/plugins/*` - `muse/cli/commands/*` are thin — delegate all logic to `muse/core/*` or plugin helpers - `muse/plugins/code/*` is the only layer that imports domain-specific AST logic - `muse/core/coordination.py` and `muse/core/indices.py` are domain-agnostic helpers --- ## 12. Type Reference ### `SymbolRecord` (TypedDict) ```python class SymbolRecord(TypedDict): kind: str # function | class | method | variable | import | … name: str # bare name qualified_name: str # dotted path (e.g. MyClass.save) lineno: int end_lineno: int content_id: str # SHA-256 of full normalized AST body_hash: str # SHA-256 of body only signature_id: str # SHA-256 of signature only metadata_id: str # SHA-256 of decorators + async + bases (v2, "" for pre-v2) canonical_key: str # {file}#{scope}#{kind}#{name}#{lineno} (v2, "" for pre-v2) ``` ### `StructuredDelta` ```python class StructuredDelta(TypedDict): domain: str ops: list[DomainOp] summary: str sem_ver_bump: SemVerBump # default "none" breaking_changes: list[str] # default [] ``` ### `DomainOp` union ```python DomainOp = InsertOp | DeleteOp | ReplaceOp | MoveOp | PatchOp ``` Each op is a `TypedDict` discriminated by a `Literal` `"op"` field. ### `ConflictRecord` (dataclass) ```python @dataclass class ConflictRecord: path: str conflict_type: str = "file_level" ours_summary: str = "" theirs_summary: str = "" addresses: list[str] = field(default_factory=list) ``` ### `Reservation` ```python class Reservation: reservation_id: str run_id: str branch: str addresses: list[str] created_at: datetime expires_at: datetime operation: str | None def is_active(self) -> bool: ... def to_dict(self) -> dict[str, str | int | list[str] | None]: ... @classmethod def from_dict(cls, d) -> Reservation: ... ``` ### `Intent` ```python class Intent: intent_id: str reservation_id: str run_id: str branch: str addresses: list[str] operation: str created_at: datetime detail: str def to_dict(self) -> dict[str, str | int | list[str]]: ... @classmethod def from_dict(cls, d) -> Intent: ... ``` ### `SemVerBump` ```python SemVerBump = Literal["major", "minor", "patch", "none"] ``` ### `Predicate` ```python Predicate = Callable[[str, SymbolRecord], bool] # first arg: file_path # second arg: SymbolRecord # returns: True if the symbol matches the predicate ``` ### `ExactClassification` ```python ExactClassification = Literal[ "rename", "move", "rename+move", "signature_only", "impl_only", "metadata_only", "full_rewrite", "unchanged", ] ``` ### `InferredRefactor` ```python InferredRefactor = Literal["extract", "inline", "split", "merge", "none"] ``` --- ## Further Reading - [Plugin Authoring Guide](plugin-authoring-guide.md) — implementing `MuseDomainPlugin` - [Type Contracts](type-contracts.md) — strict typing rules and enforcement - [CRDT Reference](crdt-reference.md) — CRDT and OT merge primitives - [Demo — Code](../demo/demo-code.md) — full narrative walkthrough of all code commands - [Demo — MIDI](../demo/midi-demo.md) — MIDI domain demo walkthrough