code-domain.md
markdown
| 1 | # Code Domain — Complete Reference |
| 2 | |
| 3 | > **Engine:** `muse/plugins/code/` · **No external deps for core analysis** |
| 4 | > **Scope:** Every command, module, type, and protocol in the code domain plugin |
| 5 | |
| 6 | --- |
| 7 | |
| 8 | ## Overview |
| 9 | |
| 10 | 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: |
| 11 | |
| 12 | - Track a function through renames and cross-file moves with perfect identity. |
| 13 | - Cherry-pick a single named function out of a historical commit. |
| 14 | - Detect exact and near-duplicate code across an entire snapshot in O(1). |
| 15 | - Predict merge conflicts before writing a single byte. |
| 16 | - Enforce architectural invariants as committed rules. |
| 17 | - Assign semantic version bumps automatically at commit time. |
| 18 | - Coordinate thousands of parallel agents without a central lock server. |
| 19 | |
| 20 | --- |
| 21 | |
| 22 | ## Contents |
| 23 | |
| 24 | 1. [Symbol Identity Model](#1-symbol-identity-model) |
| 25 | 2. [Provenance & Topology Commands](#2-provenance--topology-commands) |
| 26 | 3. [Query & Temporal Search](#3-query--temporal-search) |
| 27 | 4. [Index Infrastructure](#4-index-infrastructure) |
| 28 | 5. [Symbol Identity Detail](#5-symbol-identity-detail) |
| 29 | 6. [Multi-Agent Coordination Layer](#6-multi-agent-coordination-layer) |
| 30 | 7. [Merge Engine & Architectural Enforcement](#7-merge-engine--architectural-enforcement) |
| 31 | 8. [Semantic Versioning](#8-semantic-versioning) |
| 32 | 9. [Call-Graph Tier Commands](#9-call-graph-tier-commands) |
| 33 | 10. [Architecture Internals](#10-architecture-internals) |
| 34 | 11. [Type Reference](#11-type-reference) |
| 35 | |
| 36 | --- |
| 37 | |
| 38 | ## 1. Symbol Identity Model |
| 39 | |
| 40 | Every symbol carries four content-addressed hashes and two stable keys: |
| 41 | |
| 42 | | Field | Description | |
| 43 | |---|---| |
| 44 | | `content_id` | SHA-256 of the full normalized AST (signature + body + metadata). Two symbols are identical iff their `content_id` matches. | |
| 45 | | `body_hash` | SHA-256 of the function/class body only (excluding signature and decorators). Matches across renames and decorator changes. | |
| 46 | | `signature_id` | SHA-256 of the normalized parameter list and return annotation. Matches across implementation-only changes. | |
| 47 | | `metadata_id` *(v2)* | SHA-256 of decorator list + async flag + base classes. Matches when only the implementation or signature changed. | |
| 48 | | `canonical_key` *(v2)* | `{file}#{scope}#{kind}#{name}#{lineno}` — stable machine handle for agent-to-agent symbol handoff. | |
| 49 | | `qualified_name` | Dotted path within the file (e.g. `MyClass.my_method`). | |
| 50 | |
| 51 | ### Exact Refactor Classification |
| 52 | |
| 53 | Two symbols are classified by comparing their four hashes: |
| 54 | |
| 55 | | Classification | Condition | |
| 56 | |---|---| |
| 57 | | `unchanged` | `content_id` matches | |
| 58 | | `rename` | `body_hash` matches, name differs, same file | |
| 59 | | `move` | `content_id` matches, different file, same name | |
| 60 | | `rename+move` | `body_hash` matches, different file, different name | |
| 61 | | `signature_only` | `body_hash` matches, `signature_id` differs | |
| 62 | | `impl_only` | `signature_id` matches, `body_hash` differs | |
| 63 | | `metadata_only` | `body_hash` + `signature_id` match, `metadata_id` differs | |
| 64 | | `full_rewrite` | Both signature and body changed | |
| 65 | |
| 66 | --- |
| 67 | |
| 68 | ## 2. Provenance & Topology Commands |
| 69 | |
| 70 | ### `muse code lineage ADDRESS` |
| 71 | |
| 72 | Full provenance chain of a named symbol from its first appearance to the present. |
| 73 | |
| 74 | ``` |
| 75 | muse code lineage src/billing.py::compute_total |
| 76 | muse code lineage src/billing.py::compute_total --commit HEAD~10 |
| 77 | muse code lineage src/billing.py::compute_total --json |
| 78 | ``` |
| 79 | |
| 80 | **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. |
| 81 | |
| 82 | **Output events:** `created`, `modified`, `renamed_from`, `moved_from`, `deleted`. |
| 83 | |
| 84 | **Flags:** |
| 85 | - `--commit REF` — stop history walk at this commit (default: HEAD) |
| 86 | - `--json` — emit a JSON array of event objects |
| 87 | |
| 88 | **JSON schema:** |
| 89 | ```json |
| 90 | [ |
| 91 | { |
| 92 | "event": "created", |
| 93 | "commit_id": "a1b2c3d4...", |
| 94 | "committed_at": "2026-01-01T00:00:00+00:00", |
| 95 | "message": "Initial commit", |
| 96 | "address": "src/billing.py::compute_total", |
| 97 | "content_id": "sha256..." |
| 98 | } |
| 99 | ] |
| 100 | ``` |
| 101 | |
| 102 | --- |
| 103 | |
| 104 | ### `muse code api-surface` |
| 105 | |
| 106 | Public API surface of a snapshot — every non-underscore function, class, and method. |
| 107 | |
| 108 | ``` |
| 109 | muse code api-surface |
| 110 | muse code api-surface --commit v1.0 |
| 111 | muse code api-surface --diff v1.0 |
| 112 | muse code api-surface --json |
| 113 | ``` |
| 114 | |
| 115 | **With `--diff REF`:** Shows three sections — **Added** (new public symbols), **Removed** (deleted public symbols), **Changed** (same address, different `content_id`). |
| 116 | |
| 117 | **Public** means: `kind` in `{function, class, method, async_function}` and `name` not starting with `_`. |
| 118 | |
| 119 | --- |
| 120 | |
| 121 | ### `muse code codemap` |
| 122 | |
| 123 | Semantic topology of the entire codebase at a snapshot. |
| 124 | |
| 125 | ``` |
| 126 | muse code codemap |
| 127 | muse code codemap --top 10 |
| 128 | muse code codemap --commit HEAD~5 |
| 129 | muse code codemap --json |
| 130 | ``` |
| 131 | |
| 132 | **What it shows:** |
| 133 | - **Modules by size** — ranked by symbol count |
| 134 | - **Import graph** — in-degree (how many modules import this one) |
| 135 | - **Cycles** — import cycles detected via DFS (a hard architectural smell) |
| 136 | - **High-centrality symbols** — functions called from many places (blast-radius risk) |
| 137 | - **Boundary files** — high fan-out (imports many), zero fan-in (nothing imports them) |
| 138 | |
| 139 | **Flags:** |
| 140 | - `--top N` — show top N entries per section (default: 5) |
| 141 | - `--commit REF` — snapshot to analyse |
| 142 | - `--json` — structured output |
| 143 | |
| 144 | --- |
| 145 | |
| 146 | ### `muse code clones` |
| 147 | |
| 148 | Find exact and near-duplicate symbol clusters across the snapshot. |
| 149 | |
| 150 | ``` |
| 151 | muse code clones |
| 152 | muse code clones --tier exact |
| 153 | muse code clones --tier near |
| 154 | muse code clones --tier both |
| 155 | muse code clones --commit HEAD~3 --json |
| 156 | ``` |
| 157 | |
| 158 | **Exact clones:** Same `body_hash` at different addresses. These are literal copy-paste duplicates — same implementation, possibly different name. |
| 159 | |
| 160 | **Near-clones:** Same `signature_id`, different `body_hash`. Same public contract (parameters + return type), diverged implementation — a maintainability risk. |
| 161 | |
| 162 | **Output:** Clusters, one per group, listing all member addresses. |
| 163 | |
| 164 | --- |
| 165 | |
| 166 | ### `muse code checkout-symbol ADDRESS --commit REF` |
| 167 | |
| 168 | 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. |
| 169 | |
| 170 | ``` |
| 171 | muse code checkout-symbol src/billing.py::compute_total --commit v1.0 |
| 172 | muse code checkout-symbol src/billing.py::compute_total --commit abc123 --dry-run |
| 173 | muse code checkout-symbol src/billing.py::compute_total --commit v1.0 --json |
| 174 | ``` |
| 175 | |
| 176 | **Flags:** |
| 177 | - `--commit REF` *(required)* — source commit |
| 178 | - `--dry-run` — print the unified diff without writing |
| 179 | - `--json` — emit result as JSON for agent consumption |
| 180 | |
| 181 | **JSON output:** |
| 182 | |
| 183 | ```json |
| 184 | { |
| 185 | "address": "src/billing.py::compute_total", |
| 186 | "file": "src/billing.py", |
| 187 | "restored_from": "abc12345", |
| 188 | "dry_run": false |
| 189 | } |
| 190 | ``` |
| 191 | |
| 192 | **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. |
| 193 | |
| 194 | **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. |
| 195 | |
| 196 | --- |
| 197 | |
| 198 | ### `muse code semantic-cherry-pick ADDRESS... --from REF` |
| 199 | |
| 200 | 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. |
| 201 | |
| 202 | ``` |
| 203 | muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0 |
| 204 | muse code semantic-cherry-pick src/billing.py::f1 src/billing.py::f2 --from abc123 |
| 205 | muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0 --dry-run --json |
| 206 | ``` |
| 207 | |
| 208 | **Flags:** |
| 209 | - `--from REF` *(required)* — source commit |
| 210 | - `--dry-run` — show what would change without writing |
| 211 | - `--json` — structured output with per-symbol patch results |
| 212 | |
| 213 | **JSON output:** |
| 214 | |
| 215 | ```json |
| 216 | { |
| 217 | "from_commit": "abc12345", |
| 218 | "dry_run": false, |
| 219 | "results": [ |
| 220 | {"address": "src/billing.py::compute_total", "status": "applied", |
| 221 | "detail": "lines 10–25 → 12 lines", "old_lines": 16, "new_lines": 12} |
| 222 | ], |
| 223 | "applied": 1, |
| 224 | "failed": 0, |
| 225 | "already_current": 0 |
| 226 | } |
| 227 | ``` |
| 228 | |
| 229 | **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. |
| 230 | |
| 231 | --- |
| 232 | |
| 233 | ## 3. Query & Temporal Search |
| 234 | |
| 235 | ### `muse code query PREDICATE...` |
| 236 | |
| 237 | Symbol graph predicate DSL — SQL for your codebase. |
| 238 | |
| 239 | ``` |
| 240 | muse code query kind=function language=Python |
| 241 | muse code query "(kind=function OR kind=method) name^=_" |
| 242 | muse code query "NOT kind=import file~=billing" |
| 243 | muse code query kind=function name~=validate --all-commits |
| 244 | muse code query hash=a3f2c9 --all-commits --first |
| 245 | muse code query --commit v1.0 kind=class |
| 246 | muse code query kind=function --json |
| 247 | ``` |
| 248 | |
| 249 | #### Predicate Grammar (v2) |
| 250 | |
| 251 | ``` |
| 252 | expr = or_expr |
| 253 | or_expr = and_expr ( "OR" and_expr )* |
| 254 | and_expr = not_expr ( and_expr )* # implicit AND |
| 255 | not_expr = "NOT" primary | primary |
| 256 | primary = "(" expr ")" | atom |
| 257 | atom = KEY OP VALUE |
| 258 | ``` |
| 259 | |
| 260 | #### Operators |
| 261 | |
| 262 | | Operator | Meaning | |
| 263 | |---|---| |
| 264 | | `=` | Exact match (case-insensitive for strings) | |
| 265 | | `~=` | Contains substring | |
| 266 | | `^=` | Starts with | |
| 267 | | `$=` | Ends with | |
| 268 | | `!=` | Not equal | |
| 269 | | `>=` | Greater than or equal (lineno keys only) | |
| 270 | | `<=` | Less than or equal (lineno keys only) | |
| 271 | |
| 272 | #### Keys |
| 273 | |
| 274 | | Key | Type | Description | |
| 275 | |---|---|---| |
| 276 | | `kind` | string | `function`, `class`, `method`, `variable`, `import`, … | |
| 277 | | `language` | string | `Python`, `Go`, `Rust`, `TypeScript`, … | |
| 278 | | `name` | string | Bare symbol name | |
| 279 | | `qualified_name` | string | Dotted qualified name (e.g. `MyClass.save`) | |
| 280 | | `file` | string | File path (relative to repo root) | |
| 281 | | `hash` | string | `content_id` prefix (hex) | |
| 282 | | `body_hash` | string | `body_hash` prefix | |
| 283 | | `signature_id` | string | `signature_id` prefix | |
| 284 | | `lineno_gt` | integer | Symbol starts *after* this line number | |
| 285 | | `lineno_lt` | integer | Symbol starts *before* this line number | |
| 286 | |
| 287 | #### Flags |
| 288 | |
| 289 | | Flag | Description | |
| 290 | |---|---| |
| 291 | | `--commit REF` | Query a specific commit (mutually exclusive with `--all-commits`) | |
| 292 | | `--all-commits` | Walk all commits, deduplicate by `content_id`, annotate first-seen commit | |
| 293 | | `--first` | With `--all-commits`: keep only the first appearance of each unique body | |
| 294 | | `--json` | JSON output with `schema_version: 2` wrapper | |
| 295 | |
| 296 | --- |
| 297 | |
| 298 | ### `muse code query-history PREDICATE... [--from REF] [--to REF]` |
| 299 | |
| 300 | Temporal symbol search — track matching symbols across a commit range. |
| 301 | |
| 302 | ``` |
| 303 | muse code query-history kind=function language=Python |
| 304 | muse code query-history name~=validate --from v1.0 --to HEAD |
| 305 | muse code query-history kind=class --json |
| 306 | ``` |
| 307 | |
| 308 | **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). |
| 309 | |
| 310 | **JSON schema:** |
| 311 | ```json |
| 312 | { |
| 313 | "schema_version": 2, |
| 314 | "query": "kind=function language=Python", |
| 315 | "from_ref": "v1.0", |
| 316 | "to_ref": "HEAD", |
| 317 | "results": [ |
| 318 | { |
| 319 | "address": "src/billing.py::compute_total", |
| 320 | "first_seen": "commit_id...", |
| 321 | "last_seen": "commit_id...", |
| 322 | "commit_count": 12, |
| 323 | "change_count": 3 |
| 324 | } |
| 325 | ] |
| 326 | } |
| 327 | ``` |
| 328 | |
| 329 | --- |
| 330 | |
| 331 | ## 4. Index Infrastructure |
| 332 | |
| 333 | ### `muse code index status` |
| 334 | |
| 335 | Show present/absent/corrupt status and entry counts for all local indexes. |
| 336 | |
| 337 | ``` |
| 338 | muse code index status |
| 339 | muse code index status --json |
| 340 | ``` |
| 341 | |
| 342 | **Flags:** |
| 343 | - `--json` — emit status array as JSON |
| 344 | |
| 345 | **JSON output:** |
| 346 | |
| 347 | ```json |
| 348 | [ |
| 349 | {"name": "symbol_history", "status": "present", "entries": 1024, "updated_at": "2026-03-21T12:00:00"}, |
| 350 | {"name": "hash_occurrence", "status": "absent", "entries": 0, "updated_at": null} |
| 351 | ] |
| 352 | ``` |
| 353 | |
| 354 | ### `muse code index rebuild` |
| 355 | |
| 356 | Rebuild one or all indexes by walking the full commit history. |
| 357 | |
| 358 | ``` |
| 359 | muse code index rebuild |
| 360 | muse code index rebuild --json |
| 361 | muse code index rebuild --index symbol_history |
| 362 | muse code index rebuild --index hash_occurrence --verbose |
| 363 | ``` |
| 364 | |
| 365 | **Flags:** |
| 366 | - `--index NAME` — rebuild only this index (default: all) |
| 367 | - `--verbose, -v` — show progress while building |
| 368 | - `--json` — emit rebuild summary as JSON |
| 369 | |
| 370 | **JSON output:** |
| 371 | |
| 372 | ```json |
| 373 | { |
| 374 | "rebuilt": ["symbol_history", "hash_occurrence"], |
| 375 | "symbol_history_addresses": 512, |
| 376 | "symbol_history_events": 2048, |
| 377 | "hash_occurrence_clusters": 31, |
| 378 | "hash_occurrence_addresses": 87 |
| 379 | } |
| 380 | ``` |
| 381 | |
| 382 | ### Index Design |
| 383 | |
| 384 | Indexes live under `.muse/indices/` and are: |
| 385 | - **Derived** — computed entirely from the commit history. |
| 386 | - **Optional** — no command requires them for correctness; they only provide speed. |
| 387 | - **Fully rebuildable** — `muse code index rebuild` reconstructs them from scratch in one pass. |
| 388 | - **Versioned** — `schema_version` field for forward compatibility. |
| 389 | |
| 390 | #### `symbol_history` index |
| 391 | |
| 392 | Maps `symbol_address → list[HistoryEntry]` (chronological). Enables O(1) lineage lookups instead of O(commits × files) scans. |
| 393 | |
| 394 | #### `hash_occurrence` index |
| 395 | |
| 396 | Maps `body_hash → list[symbol_address]`. Enables O(1) clone detection and `muse code find-symbol hash=` queries. |
| 397 | |
| 398 | --- |
| 399 | |
| 400 | ## 5. Symbol Identity Detail |
| 401 | |
| 402 | ### New `SymbolRecord` fields |
| 403 | |
| 404 | `SymbolRecord` gains two backward-compatible fields (empty string `""` for pre-v2 records): |
| 405 | |
| 406 | **`metadata_id`** |
| 407 | : 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. |
| 408 | |
| 409 | **`canonical_key`** |
| 410 | : `{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. |
| 411 | |
| 412 | ### `muse code detect-refactor` (v2 output) |
| 413 | |
| 414 | With `--json`, emits `schema_version: 2` with a richer classification: |
| 415 | |
| 416 | ```json |
| 417 | { |
| 418 | "schema_version": 2, |
| 419 | "from_commit": "abc...", |
| 420 | "to_commit": "def...", |
| 421 | "total": 3, |
| 422 | "events": [ |
| 423 | { |
| 424 | "old_address": "src/billing.py::compute_total", |
| 425 | "new_address": "src/billing.py::compute_invoice_total", |
| 426 | "old_kind": "function", |
| 427 | "new_kind": "function", |
| 428 | "exact_classification": "rename", |
| 429 | "inferred_refactor": "none", |
| 430 | "confidence": 1.0, |
| 431 | "evidence": ["body_hash matches a1b2c3d4"], |
| 432 | "old_content_id": "ab12cd34", |
| 433 | "new_content_id": "ef56gh78", |
| 434 | "old_body_hash": "a1b2c3d4", |
| 435 | "new_body_hash": "a1b2c3d4" |
| 436 | } |
| 437 | ] |
| 438 | } |
| 439 | ``` |
| 440 | |
| 441 | **`exact_classification`** values: `rename`, `move`, `rename+move`, `signature_only`, `impl_only`, `metadata_only`, `full_rewrite`, `unchanged`. |
| 442 | |
| 443 | **`inferred_refactor`** values: `extract`, `inline`, `split`, `merge`, `none`. |
| 444 | |
| 445 | --- |
| 446 | |
| 447 | ## 6. Multi-Agent Coordination Layer |
| 448 | |
| 449 | 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. |
| 450 | |
| 451 | ### Storage Layout |
| 452 | |
| 453 | ``` |
| 454 | .muse/coordination/ |
| 455 | reservations/<uuid>.json advisory symbol lease |
| 456 | intents/<uuid>.json declared operation before edit |
| 457 | ``` |
| 458 | |
| 459 | All records are **write-once** (never mutated) and use TTL-based expiry. Expired records are kept for audit purposes but ignored by all commands. |
| 460 | |
| 461 | --- |
| 462 | |
| 463 | ### `muse coord reserve ADDRESS... [OPTIONS]` |
| 464 | |
| 465 | Announce intent to edit one or more symbol addresses. |
| 466 | |
| 467 | ``` |
| 468 | muse coord reserve src/billing.py::compute_total |
| 469 | muse coord reserve src/billing.py::f1 src/billing.py::f2 --run-id agent-007 --ttl 7200 |
| 470 | muse coord reserve src/billing.py::compute_total --op rename |
| 471 | muse coord reserve src/billing.py::compute_total --json |
| 472 | ``` |
| 473 | |
| 474 | **Flags:** |
| 475 | - `--run-id ID` — identifier for this agent/run (default: random UUID) |
| 476 | - `--ttl SECONDS` — reservation expiry in seconds (default: 3600) |
| 477 | - `--op OPERATION` — declared operation: `rename`, `move`, `extract`, `modify`, `delete` |
| 478 | - `--json` — JSON output |
| 479 | |
| 480 | **Conflict detection:** Warns (but never blocks) if any of the requested addresses are already reserved by another active reservation. |
| 481 | |
| 482 | **Reservation schema (v1):** |
| 483 | ```json |
| 484 | { |
| 485 | "schema_version": 1, |
| 486 | "reservation_id": "<uuid>", |
| 487 | "run_id": "<agent-supplied ID>", |
| 488 | "branch": "<current branch>", |
| 489 | "addresses": ["src/billing.py::compute_total"], |
| 490 | "created_at": "2026-03-18T12:00:00+00:00", |
| 491 | "expires_at": "2026-03-18T13:00:00+00:00", |
| 492 | "operation": "rename" |
| 493 | } |
| 494 | ``` |
| 495 | |
| 496 | --- |
| 497 | |
| 498 | ### `muse coord intent ADDRESS... --op OPERATION [OPTIONS]` |
| 499 | |
| 500 | Declare a specific operation before executing it. More precise than a reservation; enables `muse coord forecast` to produce accurate conflict predictions. |
| 501 | |
| 502 | ``` |
| 503 | muse coord intent src/billing.py::compute_total --op rename --detail "rename to compute_invoice_total" |
| 504 | muse coord intent src/billing.py::compute_total --op modify --reservation-id <uuid> |
| 505 | ``` |
| 506 | |
| 507 | **Flags:** |
| 508 | - `--op OPERATION` *(required)* — `rename`, `move`, `extract`, `modify`, `delete`, `refactor` |
| 509 | - `--detail TEXT` — free-text description of the planned change |
| 510 | - `--reservation-id UUID` — link to an existing reservation |
| 511 | - `--run-id ID` — agent identifier |
| 512 | - `--json` — JSON output |
| 513 | |
| 514 | **Intent schema (v1):** |
| 515 | ```json |
| 516 | { |
| 517 | "schema_version": 1, |
| 518 | "intent_id": "<uuid>", |
| 519 | "reservation_id": "<uuid or empty>", |
| 520 | "run_id": "<agent ID>", |
| 521 | "branch": "<current branch>", |
| 522 | "addresses": ["src/billing.py::compute_total"], |
| 523 | "operation": "rename", |
| 524 | "created_at": "2026-03-18T12:00:00+00:00", |
| 525 | "detail": "rename to compute_invoice_total" |
| 526 | } |
| 527 | ``` |
| 528 | |
| 529 | --- |
| 530 | |
| 531 | ### `muse coord forecast [OPTIONS]` |
| 532 | |
| 533 | Predict merge conflicts from active reservations and intents — **before** writing any code. |
| 534 | |
| 535 | ``` |
| 536 | muse coord forecast |
| 537 | muse coord forecast --branch feature-x |
| 538 | muse coord forecast --json |
| 539 | ``` |
| 540 | |
| 541 | **Conflict types detected:** |
| 542 | |
| 543 | | Type | Confidence | Condition | |
| 544 | |---|---|---| |
| 545 | | `address_overlap` | 1.0 | Two reservations on the same symbol address | |
| 546 | | `blast_radius_overlap` | 0.75 | Reservations on symbols that call each other (via call graph) | |
| 547 | | `operation_conflict` | 0.9 | Two reservations declare incompatible operations (e.g. both `rename`) | |
| 548 | |
| 549 | **Flags:** |
| 550 | - `--branch BRANCH` — restrict to reservations on this branch |
| 551 | - `--json` — structured conflict list |
| 552 | |
| 553 | --- |
| 554 | |
| 555 | ### `muse coord plan-merge OURS THEIRS [OPTIONS]` |
| 556 | |
| 557 | Dry-run semantic merge plan — classify all symbol conflicts without writing anything. |
| 558 | |
| 559 | ``` |
| 560 | muse coord plan-merge main feature-x |
| 561 | muse coord plan-merge HEAD~5 HEAD --json |
| 562 | ``` |
| 563 | |
| 564 | **Output:** Classifies each diverging symbol into one of: |
| 565 | - `no_conflict` — diverged in disjoint symbols |
| 566 | - `symbol_edit_overlap` — both sides modified the same symbol |
| 567 | - `rename_edit` — one side renamed, the other modified |
| 568 | - `delete_use` — one side deleted a symbol still used by the other |
| 569 | |
| 570 | **Flags:** |
| 571 | - `--json` — structured output with full classification details |
| 572 | |
| 573 | --- |
| 574 | |
| 575 | ### `muse coord shard --agents N [OPTIONS]` |
| 576 | |
| 577 | Partition the codebase into N low-coupling work zones for parallel agent assignment. |
| 578 | |
| 579 | ``` |
| 580 | muse coord shard --agents 4 |
| 581 | muse coord shard --agents 8 --language Python |
| 582 | muse coord shard --agents 4 --json |
| 583 | ``` |
| 584 | |
| 585 | **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). |
| 586 | |
| 587 | **Flags:** |
| 588 | - `--agents N` *(required)* — number of shards |
| 589 | - `--language LANG` — restrict to files of this language |
| 590 | - `--json` — shard assignments as JSON |
| 591 | |
| 592 | --- |
| 593 | |
| 594 | ### `muse coord reconcile [OPTIONS]` |
| 595 | |
| 596 | Recommend merge ordering and integration strategy from the current coordination state. |
| 597 | |
| 598 | ``` |
| 599 | muse coord reconcile |
| 600 | muse coord reconcile --json |
| 601 | ``` |
| 602 | |
| 603 | **Output:** For each active branch with reservations, recommends: |
| 604 | - **Merge order** — branches with fewer predicted conflicts should merge first |
| 605 | - **Integration strategy** — `fast-forward`, `rebase`, or `manual` (when conflicts are predicted) |
| 606 | - **Conflict hotspots** — addresses that appear in the most reservations |
| 607 | |
| 608 | --- |
| 609 | |
| 610 | ## 7. Merge Engine & Architectural Enforcement |
| 611 | |
| 612 | ### `ConflictRecord` — Structured Conflict Taxonomy |
| 613 | |
| 614 | `MergeResult` now carries `conflict_records: list[ConflictRecord]` alongside the existing `conflicts: list[str]`. Each `ConflictRecord` provides structured metadata for programmatic conflict handling: |
| 615 | |
| 616 | ```python |
| 617 | @dataclass |
| 618 | class ConflictRecord: |
| 619 | path: str |
| 620 | conflict_type: str = "file_level" # see taxonomy below |
| 621 | ours_summary: str = "" |
| 622 | theirs_summary: str = "" |
| 623 | addresses: list[str] = field(default_factory=list) |
| 624 | ``` |
| 625 | |
| 626 | **`conflict_type` taxonomy:** |
| 627 | |
| 628 | | Value | Meaning | |
| 629 | |---|---| |
| 630 | | `symbol_edit_overlap` | Both branches modified the same symbol | |
| 631 | | `rename_edit` | One branch renamed, the other modified | |
| 632 | | `move_edit` | One branch moved, the other modified | |
| 633 | | `delete_use` | One branch deleted a symbol still used by the other | |
| 634 | | `dependency_conflict` | Conflicting changes to interdependent symbols | |
| 635 | | `file_level` | Legacy — no symbol-level information available | |
| 636 | |
| 637 | --- |
| 638 | |
| 639 | ### `muse code breakage` |
| 640 | |
| 641 | Detect symbol-level structural breakage in the current working tree vs HEAD. |
| 642 | |
| 643 | ``` |
| 644 | muse code breakage |
| 645 | muse code breakage --language Python |
| 646 | muse code breakage --json |
| 647 | ``` |
| 648 | |
| 649 | **Checks performed:** |
| 650 | |
| 651 | 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). |
| 652 | 2. **`missing_interface_method`** — a class body is missing a method that exists in the HEAD snapshot's version of that class. |
| 653 | |
| 654 | **What it does NOT do:** Execute code, install packages, run mypy or a type checker, or access the network. Pure structural analysis. |
| 655 | |
| 656 | **JSON output:** |
| 657 | ```json |
| 658 | { |
| 659 | "breakage_count": 2, |
| 660 | "issues": [ |
| 661 | { |
| 662 | "issue_type": "stale_import", |
| 663 | "file": "src/billing.py", |
| 664 | "description": "imports compute_total from src/utils.py but compute_total was removed" |
| 665 | } |
| 666 | ] |
| 667 | } |
| 668 | ``` |
| 669 | |
| 670 | --- |
| 671 | |
| 672 | ### `muse code invariants` |
| 673 | |
| 674 | Enforce architectural rules declared in `.muse/invariants.toml`. |
| 675 | |
| 676 | ``` |
| 677 | muse code invariants |
| 678 | muse code invariants --commit HEAD~5 |
| 679 | muse code invariants --json |
| 680 | ``` |
| 681 | |
| 682 | **Rule types:** |
| 683 | |
| 684 | #### `no_cycles` |
| 685 | ```toml |
| 686 | [[rules]] |
| 687 | type = "no_cycles" |
| 688 | name = "no import cycles" |
| 689 | ``` |
| 690 | The import graph must be a DAG. Reports every cycle as a violation. |
| 691 | |
| 692 | #### `forbidden_dependency` |
| 693 | ```toml |
| 694 | [[rules]] |
| 695 | type = "forbidden_dependency" |
| 696 | name = "core must not import cli" |
| 697 | source_pattern = "muse/core/" |
| 698 | forbidden_pattern = "muse/cli/" |
| 699 | ``` |
| 700 | Files matching `source_pattern` must not import from files matching `forbidden_pattern`. |
| 701 | |
| 702 | #### `layer_boundary` |
| 703 | ```toml |
| 704 | [[rules]] |
| 705 | type = "layer_boundary" |
| 706 | name = "plugins must not import from cli" |
| 707 | lower = "muse/plugins/" |
| 708 | upper = "muse/cli/" |
| 709 | ``` |
| 710 | Files in `lower` must not import from files in `upper` (enforces layered architecture). |
| 711 | |
| 712 | #### `required_test` |
| 713 | ```toml |
| 714 | [[rules]] |
| 715 | type = "required_test" |
| 716 | name = "all billing functions must have tests" |
| 717 | source_pattern = "src/billing.py" |
| 718 | test_pattern = "tests/test_billing.py" |
| 719 | ``` |
| 720 | Every public function in `source_pattern` must have a corresponding test function in `test_pattern` (matched by bare name). |
| 721 | |
| 722 | **Bootstrapping:** If `.muse/invariants.toml` does not exist, `muse code invariants` creates it with a commented template and exits with a guided onboarding message. |
| 723 | |
| 724 | --- |
| 725 | |
| 726 | ## 8. Semantic Versioning |
| 727 | |
| 728 | Muse automatically assigns semantic version bumps at commit time based on the `StructuredDelta`. |
| 729 | |
| 730 | ### `SemVerBump` |
| 731 | |
| 732 | ```python |
| 733 | SemVerBump = Literal["major", "minor", "patch", "none"] |
| 734 | ``` |
| 735 | |
| 736 | ### Inference rules (`infer_sem_ver_bump`) |
| 737 | |
| 738 | | Change type | Bump | Breaking? | |
| 739 | |---|---|---| |
| 740 | | Delete a public symbol | `major` | yes — address added to `breaking_changes` | |
| 741 | | Rename a public symbol | `major` | yes — old address added to `breaking_changes` | |
| 742 | | `signature_only` change | `major` | yes — callers may break | |
| 743 | | Insert a new public symbol | `minor` | no | |
| 744 | | `impl_only` change (body only) | `patch` | no | |
| 745 | | `metadata_only` change | `none` | no | |
| 746 | | Formatting-only change | `none` | no | |
| 747 | | Non-public symbol changes | `patch` or `none` | no | |
| 748 | |
| 749 | **Public** = name does not start with `_` and kind is `function`, `class`, `method`, or `async_function`. |
| 750 | |
| 751 | ### Storage |
| 752 | |
| 753 | Both `StructuredDelta` and `CommitRecord` carry: |
| 754 | - `sem_ver_bump: SemVerBump` (default `"none"`) |
| 755 | - `breaking_changes: list[str]` (default `[]`) |
| 756 | |
| 757 | These fields are backward-compatible — pre-v2 commits read as `"none"` / `[]`. |
| 758 | |
| 759 | ### `muse log` display |
| 760 | |
| 761 | When a commit's `sem_ver_bump` is non-`none`, long-form `muse log` output appends: |
| 762 | ``` |
| 763 | SemVer: MAJOR |
| 764 | Breaking: src/billing.py::compute_total, src/billing.py::Invoice (+2 more) |
| 765 | ``` |
| 766 | |
| 767 | --- |
| 768 | |
| 769 | ## 9. Call-Graph Tier Commands |
| 770 | |
| 771 | ### `muse code impact ADDRESS [OPTIONS]` |
| 772 | |
| 773 | Transitive blast-radius analysis — what else breaks if this function changes? |
| 774 | |
| 775 | ``` |
| 776 | muse code impact src/billing.py::compute_total |
| 777 | muse code impact src/billing.py::compute_total --commit HEAD~5 |
| 778 | muse code impact src/billing.py::compute_total --json |
| 779 | ``` |
| 780 | |
| 781 | **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. |
| 782 | |
| 783 | **Risk levels:** 🟢 (0–2 callers), 🟡 (3–9 callers), 🔴 (10+ callers). |
| 784 | |
| 785 | --- |
| 786 | |
| 787 | ### `muse code dead [OPTIONS]` |
| 788 | |
| 789 | Dead code detection — symbols with no callers and no importers. |
| 790 | |
| 791 | ``` |
| 792 | muse code dead |
| 793 | muse code dead --kind function |
| 794 | muse code dead --exclude-tests |
| 795 | muse code dead --json |
| 796 | ``` |
| 797 | |
| 798 | **Detection logic:** A symbol is a dead-code candidate when: |
| 799 | 1. Its bare name appears in no `ast.Call` node in the snapshot **and** |
| 800 | 2. Its module is not imported anywhere in the snapshot. |
| 801 | |
| 802 | **Distinction:** `definite_dead` (module never imported) vs `soft_dead` (module imported but function never called directly). |
| 803 | |
| 804 | --- |
| 805 | |
| 806 | ### `muse code coverage CLASS_ADDRESS [OPTIONS]` |
| 807 | |
| 808 | Class interface call-coverage — which methods of a class are actually called? |
| 809 | |
| 810 | ``` |
| 811 | muse code coverage src/billing.py::Invoice |
| 812 | muse code coverage src/billing.py::Invoice --show-callers |
| 813 | muse code coverage src/billing.py::Invoice --json |
| 814 | ``` |
| 815 | |
| 816 | **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. |
| 817 | |
| 818 | --- |
| 819 | |
| 820 | ### `muse code deps ADDRESS_OR_FILE [OPTIONS]` |
| 821 | |
| 822 | Import graph + call-graph analysis. |
| 823 | |
| 824 | ``` |
| 825 | muse code deps src/billing.py |
| 826 | muse code deps src/billing.py --reverse |
| 827 | muse code deps src/billing.py::compute_total |
| 828 | muse code deps src/billing.py::compute_total --reverse |
| 829 | muse code deps src/billing.py --commit v1.0 --json |
| 830 | ``` |
| 831 | |
| 832 | **File mode:** Lists all `import`-kind symbols from the file (what does it import?). With `--reverse`: which other files import this one. |
| 833 | |
| 834 | **Symbol mode** (`address` contains `::`): Python-only call extraction — which functions does this function call? With `--reverse`: which functions call this one. |
| 835 | |
| 836 | --- |
| 837 | |
| 838 | ### `muse code find-symbol [OPTIONS]` |
| 839 | |
| 840 | Cross-commit, cross-branch symbol search by hash, name, or kind. |
| 841 | |
| 842 | ``` |
| 843 | muse code find-symbol --hash a3f2c9 |
| 844 | muse code find-symbol --name compute_total |
| 845 | muse code find-symbol --name compute_* --kind function |
| 846 | muse code find-symbol --hash a3f2c9 --all-branches --first |
| 847 | muse code find-symbol --name validate --json |
| 848 | ``` |
| 849 | |
| 850 | **Flags:** |
| 851 | - `--hash HEX` — match `content_id` prefix (exact body match across history) |
| 852 | - `--name NAME` — exact name or prefix glob with `*` |
| 853 | - `--kind KIND` — restrict to symbol kind |
| 854 | - `--all-branches` — also scan all branch tips in `.muse/refs/heads/` |
| 855 | - `--first` — deduplicate on `content_id`, keeping only the first appearance |
| 856 | - `--json` — structured output |
| 857 | |
| 858 | --- |
| 859 | |
| 860 | ### `muse code patch ADDRESS SOURCE [OPTIONS]` |
| 861 | |
| 862 | Surgical semantic patch — replace exactly one named symbol in the working tree. |
| 863 | |
| 864 | ``` |
| 865 | muse code patch src/billing.py::compute_total new_impl.py |
| 866 | echo "def compute_total(x): return x * 2" | muse code patch src/billing.py::compute_total - |
| 867 | muse code patch src/billing.py::compute_total new_impl.py --dry-run |
| 868 | muse code patch src/billing.py::compute_total new_impl.py --json |
| 869 | ``` |
| 870 | |
| 871 | **Syntax validation:** Before writing, validates the replacement source with: |
| 872 | - `ast.parse` for Python |
| 873 | - `tree-sitter` CST error-node check for all 11 supported languages |
| 874 | |
| 875 | Rejects the patch and exits non-zero if the source has syntax errors. |
| 876 | |
| 877 | **Flags:** |
| 878 | - `--body, -b FILE` *(required)* — file containing the replacement source (`-` for stdin) |
| 879 | - `--dry-run, -n` — print what would change without writing |
| 880 | - `--json` — emit result as JSON for agent consumption |
| 881 | |
| 882 | **JSON output:** |
| 883 | |
| 884 | ```json |
| 885 | { |
| 886 | "address": "src/billing.py::compute_total", |
| 887 | "file": "src/billing.py", |
| 888 | "lines_replaced": 12, |
| 889 | "new_lines": 9, |
| 890 | "dry_run": false |
| 891 | } |
| 892 | ``` |
| 893 | |
| 894 | **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. |
| 895 | |
| 896 | --- |
| 897 | |
| 898 | ### `muse grep PATTERN [OPTIONS]` |
| 899 | |
| 900 | 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. |
| 901 | |
| 902 | ``` |
| 903 | muse grep validate |
| 904 | muse grep "^handle" --regex |
| 905 | muse grep Invoice --kind class |
| 906 | muse grep compute --language Go |
| 907 | muse grep total --commit HEAD~5 |
| 908 | muse grep validate --json |
| 909 | ``` |
| 910 | |
| 911 | **Flags:** |
| 912 | |
| 913 | | Flag | Short | Description | |
| 914 | |---|---|---| |
| 915 | | `--regex, -e` | | Treat PATTERN as a Python regex (default: substring match) | |
| 916 | | `--kind KIND, -k` | | Restrict to symbols of this kind (function, class, method, …) | |
| 917 | | `--language LANG, -l` | | Restrict to files of this language (Python, Go, …) | |
| 918 | | `--commit REF, -c` | | Search a historical commit instead of HEAD | |
| 919 | | `--hashes` | | Include 8-char content-ID prefix in output | |
| 920 | | `--json` | | Emit results as JSON | |
| 921 | |
| 922 | **JSON output:** |
| 923 | |
| 924 | ```json |
| 925 | [ |
| 926 | { |
| 927 | "address": "src/auth.py::validate_token", |
| 928 | "kind": "function", |
| 929 | "name": "validate_token", |
| 930 | "qualified_name": "validate_token", |
| 931 | "file": "src/auth.py", |
| 932 | "lineno": 14, |
| 933 | "language": "Python", |
| 934 | "content_id": "cb4afa1234567890..." |
| 935 | } |
| 936 | ] |
| 937 | ``` |
| 938 | |
| 939 | **Security:** Patterns are capped at 512 characters to prevent ReDoS. Invalid regex syntax is caught and reported as exit 1 rather than crashing. |
| 940 | |
| 941 | --- |
| 942 | |
| 943 | ### `muse code-check [COMMIT] [OPTIONS]` |
| 944 | |
| 945 | Enforce semantic code invariants against a commit snapshot. |
| 946 | |
| 947 | ``` |
| 948 | muse code-check # check HEAD |
| 949 | muse code-check abc1234 # check specific commit |
| 950 | muse code-check --strict # exit 1 on any error-severity violation |
| 951 | muse code-check --json # machine-readable JSON output |
| 952 | muse code-check --rules my_rules.toml # custom rules file inside the repo |
| 953 | ``` |
| 954 | |
| 955 | **Flags:** |
| 956 | |
| 957 | | Flag | Description | |
| 958 | |---|---| |
| 959 | | `COMMIT` | Commit ID to check (default: HEAD) | |
| 960 | | `--strict` | Exit 1 when any error-severity violation is found | |
| 961 | | `--json` | Emit machine-readable JSON | |
| 962 | | `--rules FILE` | Path to a TOML invariants file **inside the repo** (default: `.muse/code_invariants.toml`) | |
| 963 | |
| 964 | **Security:** `--rules FILE` is validated via `contain_path()` — paths that escape the repo root are rejected with exit 1. |
| 965 | |
| 966 | --- |
| 967 | |
| 968 | ## 10. Architecture Internals |
| 969 | |
| 970 | ### Module Map |
| 971 | |
| 972 | ``` |
| 973 | muse/ |
| 974 | plugins/code/ |
| 975 | plugin.py MidiPlugin → CodePlugin (MuseDomainPlugin + StructuredMergePlugin) |
| 976 | ast_parser.py Python AST → SymbolRecord; validate_syntax() for all 11 languages |
| 977 | symbol_diff.py diff_symbol_trees() — O(n) diffing, rename/move annotation |
| 978 | _query.py symbols_for_snapshot(), walk_commits(), language_of() |
| 979 | _predicate.py Predicate DSL parser — tokenise → recursive descent → Predicate callable |
| 980 | _callgraph.py ForwardGraph, ReverseGraph, build_*, transitive_callers BFS |
| 981 | _refactor_classify.py classify_exact(), classify_composite(), RefactorClassification |
| 982 | core/ |
| 983 | coordination.py Reservation, Intent, create/load helpers, .muse/coordination/ |
| 984 | indices.py SymbolHistoryIndex, HashOccurrenceIndex, save/load/rebuild |
| 985 | ``` |
| 986 | |
| 987 | ### Language Support |
| 988 | |
| 989 | | Language | Extension(s) | Parser | Symbol types | |
| 990 | |---|---|---|---| |
| 991 | | Python | `.py` | `ast` (stdlib) | function, async_function, class, method, variable, import | |
| 992 | | JavaScript | `.js` `.jsx` `.mjs` `.cjs` | tree-sitter | function, class, method | |
| 993 | | TypeScript | `.ts` `.tsx` | tree-sitter | function, class, method, interface, type_alias, enum | |
| 994 | | Go | `.go` | tree-sitter | function (method qualified as `Type.Method`) | |
| 995 | | Rust | `.rs` | tree-sitter | function (impl method qualified as `Type.method`) | |
| 996 | | Java | `.java` | tree-sitter | class, interface, method, constructor, enum | |
| 997 | | C | `.c` `.h` | tree-sitter | function_definition | |
| 998 | | C++ | `.cpp` `.cc` `.cxx` `.hpp` | tree-sitter | function, class, struct | |
| 999 | | C# | `.cs` | tree-sitter | class, interface, struct, method, constructor, enum | |
| 1000 | | Ruby | `.rb` | tree-sitter | class, module, method, singleton_method | |
| 1001 | | Kotlin | `.kt` `.kts` | tree-sitter | function, class, method | |
| 1002 | |
| 1003 | ### Layer Rules |
| 1004 | |
| 1005 | - `muse/core/*` is domain-agnostic — never imports from `muse/plugins/*` |
| 1006 | - `muse/cli/commands/*` are thin — delegate all logic to `muse/core/*` or plugin helpers |
| 1007 | - `muse/plugins/code/*` is the only layer that imports domain-specific AST logic |
| 1008 | - `muse/core/coordination.py` and `muse/core/indices.py` are domain-agnostic helpers |
| 1009 | |
| 1010 | --- |
| 1011 | |
| 1012 | ## 11. Type Reference |
| 1013 | |
| 1014 | ### `SymbolRecord` (TypedDict) |
| 1015 | |
| 1016 | ```python |
| 1017 | class SymbolRecord(TypedDict): |
| 1018 | kind: str # function | class | method | variable | import | … |
| 1019 | name: str # bare name |
| 1020 | qualified_name: str # dotted path (e.g. MyClass.save) |
| 1021 | lineno: int |
| 1022 | end_lineno: int |
| 1023 | content_id: str # SHA-256 of full normalized AST |
| 1024 | body_hash: str # SHA-256 of body only |
| 1025 | signature_id: str # SHA-256 of signature only |
| 1026 | metadata_id: str # SHA-256 of decorators + async + bases (v2, "" for pre-v2) |
| 1027 | canonical_key: str # {file}#{scope}#{kind}#{name}#{lineno} (v2, "" for pre-v2) |
| 1028 | ``` |
| 1029 | |
| 1030 | ### `StructuredDelta` |
| 1031 | |
| 1032 | ```python |
| 1033 | class StructuredDelta(TypedDict): |
| 1034 | domain: str |
| 1035 | ops: list[DomainOp] |
| 1036 | summary: str |
| 1037 | sem_ver_bump: SemVerBump # default "none" |
| 1038 | breaking_changes: list[str] # default [] |
| 1039 | ``` |
| 1040 | |
| 1041 | ### `DomainOp` union |
| 1042 | |
| 1043 | ```python |
| 1044 | DomainOp = InsertOp | DeleteOp | ReplaceOp | MoveOp | PatchOp |
| 1045 | ``` |
| 1046 | |
| 1047 | Each op is a `TypedDict` discriminated by a `Literal` `"op"` field. |
| 1048 | |
| 1049 | ### `ConflictRecord` (dataclass) |
| 1050 | |
| 1051 | ```python |
| 1052 | @dataclass |
| 1053 | class ConflictRecord: |
| 1054 | path: str |
| 1055 | conflict_type: str = "file_level" |
| 1056 | ours_summary: str = "" |
| 1057 | theirs_summary: str = "" |
| 1058 | addresses: list[str] = field(default_factory=list) |
| 1059 | ``` |
| 1060 | |
| 1061 | ### `Reservation` |
| 1062 | |
| 1063 | ```python |
| 1064 | class Reservation: |
| 1065 | reservation_id: str |
| 1066 | run_id: str |
| 1067 | branch: str |
| 1068 | addresses: list[str] |
| 1069 | created_at: datetime |
| 1070 | expires_at: datetime |
| 1071 | operation: str | None |
| 1072 | def is_active(self) -> bool: ... |
| 1073 | def to_dict(self) -> dict[str, str | int | list[str] | None]: ... |
| 1074 | @classmethod |
| 1075 | def from_dict(cls, d) -> Reservation: ... |
| 1076 | ``` |
| 1077 | |
| 1078 | ### `Intent` |
| 1079 | |
| 1080 | ```python |
| 1081 | class Intent: |
| 1082 | intent_id: str |
| 1083 | reservation_id: str |
| 1084 | run_id: str |
| 1085 | branch: str |
| 1086 | addresses: list[str] |
| 1087 | operation: str |
| 1088 | created_at: datetime |
| 1089 | detail: str |
| 1090 | def to_dict(self) -> dict[str, str | int | list[str]]: ... |
| 1091 | @classmethod |
| 1092 | def from_dict(cls, d) -> Intent: ... |
| 1093 | ``` |
| 1094 | |
| 1095 | ### `SemVerBump` |
| 1096 | |
| 1097 | ```python |
| 1098 | SemVerBump = Literal["major", "minor", "patch", "none"] |
| 1099 | ``` |
| 1100 | |
| 1101 | ### `Predicate` |
| 1102 | |
| 1103 | ```python |
| 1104 | Predicate = Callable[[str, SymbolRecord], bool] |
| 1105 | # first arg: file_path |
| 1106 | # second arg: SymbolRecord |
| 1107 | # returns: True if the symbol matches the predicate |
| 1108 | ``` |
| 1109 | |
| 1110 | ### `ExactClassification` |
| 1111 | |
| 1112 | ```python |
| 1113 | ExactClassification = Literal[ |
| 1114 | "rename", "move", "rename+move", |
| 1115 | "signature_only", "impl_only", "metadata_only", |
| 1116 | "full_rewrite", "unchanged", |
| 1117 | ] |
| 1118 | ``` |
| 1119 | |
| 1120 | ### `InferredRefactor` |
| 1121 | |
| 1122 | ```python |
| 1123 | InferredRefactor = Literal["extract", "inline", "split", "merge", "none"] |
| 1124 | ``` |
| 1125 | |
| 1126 | --- |
| 1127 | |
| 1128 | ## Further Reading |
| 1129 | |
| 1130 | - [Plugin Authoring Guide](plugin-authoring-guide.md) — implementing `MuseDomainPlugin` |
| 1131 | - [Type Contracts](type-contracts.md) — strict typing rules and enforcement |
| 1132 | - [CRDT Reference](crdt-reference.md) — CRDT and OT merge primitives |
| 1133 | - [Demo — Code](../demo/demo-code.md) — full narrative walkthrough of all code commands |
| 1134 | - [Demo — MIDI](../demo/midi-demo.md) — MIDI domain demo walkthrough |