cgcardona / muse public
code-domain.md markdown
988 lines 31.2 KB
1f0a7cd9 docs: rename demo-midi.md → midi-demo.md and add full MIDI domain reference Gabriel Cardona <gabriel@tellurstori.com> 15h ago
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 ```
174
175 **Flags:**
176 - `--commit REF` *(required)* — source commit
177 - `--dry-run` — print the unified diff without writing
178
179 **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.
180
181 ---
182
183 ### `muse code semantic-cherry-pick ADDRESS... --from REF`
184
185 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.
186
187 ```
188 muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0
189 muse code semantic-cherry-pick src/billing.py::f1 src/billing.py::f2 --from abc123
190 muse code semantic-cherry-pick src/billing.py::compute_total --from v1.0 --dry-run --json
191 ```
192
193 **Flags:**
194 - `--from REF` *(required)* — source commit
195 - `--dry-run` — show what would change without writing
196 - `--json` — structured output with per-symbol patch results
197
198 ---
199
200 ## 3. Query & Temporal Search
201
202 ### `muse code query PREDICATE...`
203
204 Symbol graph predicate DSL — SQL for your codebase.
205
206 ```
207 muse code query kind=function language=Python
208 muse code query "(kind=function OR kind=method) name^=_"
209 muse code query "NOT kind=import file~=billing"
210 muse code query kind=function name~=validate --all-commits
211 muse code query hash=a3f2c9 --all-commits --first
212 muse code query --commit v1.0 kind=class
213 muse code query kind=function --json
214 ```
215
216 #### Predicate Grammar (v2)
217
218 ```
219 expr = or_expr
220 or_expr = and_expr ( "OR" and_expr )*
221 and_expr = not_expr ( and_expr )* # implicit AND
222 not_expr = "NOT" primary | primary
223 primary = "(" expr ")" | atom
224 atom = KEY OP VALUE
225 ```
226
227 #### Operators
228
229 | Operator | Meaning |
230 |---|---|
231 | `=` | Exact match (case-insensitive for strings) |
232 | `~=` | Contains substring |
233 | `^=` | Starts with |
234 | `$=` | Ends with |
235 | `!=` | Not equal |
236 | `>=` | Greater than or equal (lineno keys only) |
237 | `<=` | Less than or equal (lineno keys only) |
238
239 #### Keys
240
241 | Key | Type | Description |
242 |---|---|---|
243 | `kind` | string | `function`, `class`, `method`, `variable`, `import`, … |
244 | `language` | string | `Python`, `Go`, `Rust`, `TypeScript`, … |
245 | `name` | string | Bare symbol name |
246 | `qualified_name` | string | Dotted qualified name (e.g. `MyClass.save`) |
247 | `file` | string | File path (relative to repo root) |
248 | `hash` | string | `content_id` prefix (hex) |
249 | `body_hash` | string | `body_hash` prefix |
250 | `signature_id` | string | `signature_id` prefix |
251 | `lineno_gt` | integer | Symbol starts *after* this line number |
252 | `lineno_lt` | integer | Symbol starts *before* this line number |
253
254 #### Flags
255
256 | Flag | Description |
257 |---|---|
258 | `--commit REF` | Query a specific commit (mutually exclusive with `--all-commits`) |
259 | `--all-commits` | Walk all commits, deduplicate by `content_id`, annotate first-seen commit |
260 | `--first` | With `--all-commits`: keep only the first appearance of each unique body |
261 | `--json` | JSON output with `schema_version: 2` wrapper |
262
263 ---
264
265 ### `muse code query-history PREDICATE... [--from REF] [--to REF]`
266
267 Temporal symbol search — track matching symbols across a commit range.
268
269 ```
270 muse code query-history kind=function language=Python
271 muse code query-history name~=validate --from v1.0 --to HEAD
272 muse code query-history kind=class --json
273 ```
274
275 **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).
276
277 **JSON schema:**
278 ```json
279 {
280 "schema_version": 2,
281 "query": "kind=function language=Python",
282 "from_ref": "v1.0",
283 "to_ref": "HEAD",
284 "results": [
285 {
286 "address": "src/billing.py::compute_total",
287 "first_seen": "commit_id...",
288 "last_seen": "commit_id...",
289 "commit_count": 12,
290 "change_count": 3
291 }
292 ]
293 }
294 ```
295
296 ---
297
298 ## 4. Index Infrastructure
299
300 ### `muse code index status`
301
302 Show present/absent/corrupt status and entry counts for all local indexes.
303
304 ```
305 muse code index status
306 muse code index status --json
307 ```
308
309 ### `muse code index rebuild`
310
311 Rebuild one or all indexes by walking the full commit history.
312
313 ```
314 muse code index rebuild
315 muse code index rebuild --index symbol_history
316 muse code index rebuild --index hash_occurrence
317 ```
318
319 **Flags:**
320 - `--index NAME` — rebuild only this index (default: all)
321
322 ### Index Design
323
324 Indexes live under `.muse/indices/` and are:
325 - **Derived** — computed entirely from the commit history.
326 - **Optional** — no command requires them for correctness; they only provide speed.
327 - **Fully rebuildable** — `muse code index rebuild` reconstructs them from scratch in one pass.
328 - **Versioned** — `schema_version` field for forward compatibility.
329
330 #### `symbol_history` index
331
332 Maps `symbol_address → list[HistoryEntry]` (chronological). Enables O(1) lineage lookups instead of O(commits × files) scans.
333
334 #### `hash_occurrence` index
335
336 Maps `body_hash → list[symbol_address]`. Enables O(1) clone detection and `muse code find-symbol hash=` queries.
337
338 ---
339
340 ## 5. Symbol Identity Detail
341
342 ### New `SymbolRecord` fields
343
344 `SymbolRecord` gains two backward-compatible fields (empty string `""` for pre-v2 records):
345
346 **`metadata_id`**
347 : 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.
348
349 **`canonical_key`**
350 : `{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.
351
352 ### `muse code detect-refactor` (v2 output)
353
354 With `--json`, emits `schema_version: 2` with a richer classification:
355
356 ```json
357 {
358 "schema_version": 2,
359 "from_commit": "abc...",
360 "to_commit": "def...",
361 "total": 3,
362 "events": [
363 {
364 "old_address": "src/billing.py::compute_total",
365 "new_address": "src/billing.py::compute_invoice_total",
366 "old_kind": "function",
367 "new_kind": "function",
368 "exact_classification": "rename",
369 "inferred_refactor": "none",
370 "confidence": 1.0,
371 "evidence": ["body_hash matches a1b2c3d4"],
372 "old_content_id": "ab12cd34",
373 "new_content_id": "ef56gh78",
374 "old_body_hash": "a1b2c3d4",
375 "new_body_hash": "a1b2c3d4"
376 }
377 ]
378 }
379 ```
380
381 **`exact_classification`** values: `rename`, `move`, `rename+move`, `signature_only`, `impl_only`, `metadata_only`, `full_rewrite`, `unchanged`.
382
383 **`inferred_refactor`** values: `extract`, `inline`, `split`, `merge`, `none`.
384
385 ---
386
387 ## 6. Multi-Agent Coordination Layer
388
389 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.
390
391 ### Storage Layout
392
393 ```
394 .muse/coordination/
395 reservations/<uuid>.json advisory symbol lease
396 intents/<uuid>.json declared operation before edit
397 ```
398
399 All records are **write-once** (never mutated) and use TTL-based expiry. Expired records are kept for audit purposes but ignored by all commands.
400
401 ---
402
403 ### `muse coord reserve ADDRESS... [OPTIONS]`
404
405 Announce intent to edit one or more symbol addresses.
406
407 ```
408 muse coord reserve src/billing.py::compute_total
409 muse coord reserve src/billing.py::f1 src/billing.py::f2 --run-id agent-007 --ttl 7200
410 muse coord reserve src/billing.py::compute_total --op rename
411 muse coord reserve src/billing.py::compute_total --json
412 ```
413
414 **Flags:**
415 - `--run-id ID` — identifier for this agent/run (default: random UUID)
416 - `--ttl SECONDS` — reservation expiry in seconds (default: 3600)
417 - `--op OPERATION` — declared operation: `rename`, `move`, `extract`, `modify`, `delete`
418 - `--json` — JSON output
419
420 **Conflict detection:** Warns (but never blocks) if any of the requested addresses are already reserved by another active reservation.
421
422 **Reservation schema (v1):**
423 ```json
424 {
425 "schema_version": 1,
426 "reservation_id": "<uuid>",
427 "run_id": "<agent-supplied ID>",
428 "branch": "<current branch>",
429 "addresses": ["src/billing.py::compute_total"],
430 "created_at": "2026-03-18T12:00:00+00:00",
431 "expires_at": "2026-03-18T13:00:00+00:00",
432 "operation": "rename"
433 }
434 ```
435
436 ---
437
438 ### `muse coord intent ADDRESS... --op OPERATION [OPTIONS]`
439
440 Declare a specific operation before executing it. More precise than a reservation; enables `muse coord forecast` to produce accurate conflict predictions.
441
442 ```
443 muse coord intent src/billing.py::compute_total --op rename --detail "rename to compute_invoice_total"
444 muse coord intent src/billing.py::compute_total --op modify --reservation-id <uuid>
445 ```
446
447 **Flags:**
448 - `--op OPERATION` *(required)* — `rename`, `move`, `extract`, `modify`, `delete`, `refactor`
449 - `--detail TEXT` — free-text description of the planned change
450 - `--reservation-id UUID` — link to an existing reservation
451 - `--run-id ID` — agent identifier
452 - `--json` — JSON output
453
454 **Intent schema (v1):**
455 ```json
456 {
457 "schema_version": 1,
458 "intent_id": "<uuid>",
459 "reservation_id": "<uuid or empty>",
460 "run_id": "<agent ID>",
461 "branch": "<current branch>",
462 "addresses": ["src/billing.py::compute_total"],
463 "operation": "rename",
464 "created_at": "2026-03-18T12:00:00+00:00",
465 "detail": "rename to compute_invoice_total"
466 }
467 ```
468
469 ---
470
471 ### `muse coord forecast [OPTIONS]`
472
473 Predict merge conflicts from active reservations and intents — **before** writing any code.
474
475 ```
476 muse coord forecast
477 muse coord forecast --branch feature-x
478 muse coord forecast --json
479 ```
480
481 **Conflict types detected:**
482
483 | Type | Confidence | Condition |
484 |---|---|---|
485 | `address_overlap` | 1.0 | Two reservations on the same symbol address |
486 | `blast_radius_overlap` | 0.75 | Reservations on symbols that call each other (via call graph) |
487 | `operation_conflict` | 0.9 | Two reservations declare incompatible operations (e.g. both `rename`) |
488
489 **Flags:**
490 - `--branch BRANCH` — restrict to reservations on this branch
491 - `--json` — structured conflict list
492
493 ---
494
495 ### `muse coord plan-merge OURS THEIRS [OPTIONS]`
496
497 Dry-run semantic merge plan — classify all symbol conflicts without writing anything.
498
499 ```
500 muse coord plan-merge main feature-x
501 muse coord plan-merge HEAD~5 HEAD --json
502 ```
503
504 **Output:** Classifies each diverging symbol into one of:
505 - `no_conflict` — diverged in disjoint symbols
506 - `symbol_edit_overlap` — both sides modified the same symbol
507 - `rename_edit` — one side renamed, the other modified
508 - `delete_use` — one side deleted a symbol still used by the other
509
510 **Flags:**
511 - `--json` — structured output with full classification details
512
513 ---
514
515 ### `muse coord shard --agents N [OPTIONS]`
516
517 Partition the codebase into N low-coupling work zones for parallel agent assignment.
518
519 ```
520 muse coord shard --agents 4
521 muse coord shard --agents 8 --language Python
522 muse coord shard --agents 4 --json
523 ```
524
525 **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).
526
527 **Flags:**
528 - `--agents N` *(required)* — number of shards
529 - `--language LANG` — restrict to files of this language
530 - `--json` — shard assignments as JSON
531
532 ---
533
534 ### `muse coord reconcile [OPTIONS]`
535
536 Recommend merge ordering and integration strategy from the current coordination state.
537
538 ```
539 muse coord reconcile
540 muse coord reconcile --json
541 ```
542
543 **Output:** For each active branch with reservations, recommends:
544 - **Merge order** — branches with fewer predicted conflicts should merge first
545 - **Integration strategy** — `fast-forward`, `rebase`, or `manual` (when conflicts are predicted)
546 - **Conflict hotspots** — addresses that appear in the most reservations
547
548 ---
549
550 ## 7. Merge Engine & Architectural Enforcement
551
552 ### `ConflictRecord` — Structured Conflict Taxonomy
553
554 `MergeResult` now carries `conflict_records: list[ConflictRecord]` alongside the existing `conflicts: list[str]`. Each `ConflictRecord` provides structured metadata for programmatic conflict handling:
555
556 ```python
557 @dataclass
558 class ConflictRecord:
559 path: str
560 conflict_type: str = "file_level" # see taxonomy below
561 ours_summary: str = ""
562 theirs_summary: str = ""
563 addresses: list[str] = field(default_factory=list)
564 ```
565
566 **`conflict_type` taxonomy:**
567
568 | Value | Meaning |
569 |---|---|
570 | `symbol_edit_overlap` | Both branches modified the same symbol |
571 | `rename_edit` | One branch renamed, the other modified |
572 | `move_edit` | One branch moved, the other modified |
573 | `delete_use` | One branch deleted a symbol still used by the other |
574 | `dependency_conflict` | Conflicting changes to interdependent symbols |
575 | `file_level` | Legacy — no symbol-level information available |
576
577 ---
578
579 ### `muse code breakage`
580
581 Detect symbol-level structural breakage in the current working tree vs HEAD.
582
583 ```
584 muse code breakage
585 muse code breakage --language Python
586 muse code breakage --json
587 ```
588
589 **Checks performed:**
590
591 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).
592 2. **`missing_interface_method`** — a class body is missing a method that exists in the HEAD snapshot's version of that class.
593
594 **What it does NOT do:** Execute code, install packages, run mypy or a type checker, or access the network. Pure structural analysis.
595
596 **JSON output:**
597 ```json
598 {
599 "breakage_count": 2,
600 "issues": [
601 {
602 "issue_type": "stale_import",
603 "file": "src/billing.py",
604 "description": "imports compute_total from src/utils.py but compute_total was removed"
605 }
606 ]
607 }
608 ```
609
610 ---
611
612 ### `muse code invariants`
613
614 Enforce architectural rules declared in `.muse/invariants.toml`.
615
616 ```
617 muse code invariants
618 muse code invariants --commit HEAD~5
619 muse code invariants --json
620 ```
621
622 **Rule types:**
623
624 #### `no_cycles`
625 ```toml
626 [[rules]]
627 type = "no_cycles"
628 name = "no import cycles"
629 ```
630 The import graph must be a DAG. Reports every cycle as a violation.
631
632 #### `forbidden_dependency`
633 ```toml
634 [[rules]]
635 type = "forbidden_dependency"
636 name = "core must not import cli"
637 source_pattern = "muse/core/"
638 forbidden_pattern = "muse/cli/"
639 ```
640 Files matching `source_pattern` must not import from files matching `forbidden_pattern`.
641
642 #### `layer_boundary`
643 ```toml
644 [[rules]]
645 type = "layer_boundary"
646 name = "plugins must not import from cli"
647 lower = "muse/plugins/"
648 upper = "muse/cli/"
649 ```
650 Files in `lower` must not import from files in `upper` (enforces layered architecture).
651
652 #### `required_test`
653 ```toml
654 [[rules]]
655 type = "required_test"
656 name = "all billing functions must have tests"
657 source_pattern = "src/billing.py"
658 test_pattern = "tests/test_billing.py"
659 ```
660 Every public function in `source_pattern` must have a corresponding test function in `test_pattern` (matched by bare name).
661
662 **Bootstrapping:** If `.muse/invariants.toml` does not exist, `muse code invariants` creates it with a commented template and exits with a guided onboarding message.
663
664 ---
665
666 ## 8. Semantic Versioning
667
668 Muse automatically assigns semantic version bumps at commit time based on the `StructuredDelta`.
669
670 ### `SemVerBump`
671
672 ```python
673 SemVerBump = Literal["major", "minor", "patch", "none"]
674 ```
675
676 ### Inference rules (`infer_sem_ver_bump`)
677
678 | Change type | Bump | Breaking? |
679 |---|---|---|
680 | Delete a public symbol | `major` | yes — address added to `breaking_changes` |
681 | Rename a public symbol | `major` | yes — old address added to `breaking_changes` |
682 | `signature_only` change | `major` | yes — callers may break |
683 | Insert a new public symbol | `minor` | no |
684 | `impl_only` change (body only) | `patch` | no |
685 | `metadata_only` change | `none` | no |
686 | Formatting-only change | `none` | no |
687 | Non-public symbol changes | `patch` or `none` | no |
688
689 **Public** = name does not start with `_` and kind is `function`, `class`, `method`, or `async_function`.
690
691 ### Storage
692
693 Both `StructuredDelta` and `CommitRecord` carry:
694 - `sem_ver_bump: SemVerBump` (default `"none"`)
695 - `breaking_changes: list[str]` (default `[]`)
696
697 These fields are backward-compatible — pre-v2 commits read as `"none"` / `[]`.
698
699 ### `muse log` display
700
701 When a commit's `sem_ver_bump` is non-`none`, long-form `muse log` output appends:
702 ```
703 SemVer: MAJOR
704 Breaking: src/billing.py::compute_total, src/billing.py::Invoice (+2 more)
705 ```
706
707 ---
708
709 ## 9. Call-Graph Tier Commands
710
711 ### `muse code impact ADDRESS [OPTIONS]`
712
713 Transitive blast-radius analysis — what else breaks if this function changes?
714
715 ```
716 muse code impact src/billing.py::compute_total
717 muse code impact src/billing.py::compute_total --commit HEAD~5
718 muse code impact src/billing.py::compute_total --json
719 ```
720
721 **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.
722
723 **Risk levels:** 🟢 (0–2 callers), 🟡 (3–9 callers), 🔴 (10+ callers).
724
725 ---
726
727 ### `muse code dead [OPTIONS]`
728
729 Dead code detection — symbols with no callers and no importers.
730
731 ```
732 muse code dead
733 muse code dead --kind function
734 muse code dead --exclude-tests
735 muse code dead --json
736 ```
737
738 **Detection logic:** A symbol is a dead-code candidate when:
739 1. Its bare name appears in no `ast.Call` node in the snapshot **and**
740 2. Its module is not imported anywhere in the snapshot.
741
742 **Distinction:** `definite_dead` (module never imported) vs `soft_dead` (module imported but function never called directly).
743
744 ---
745
746 ### `muse code coverage CLASS_ADDRESS [OPTIONS]`
747
748 Class interface call-coverage — which methods of a class are actually called?
749
750 ```
751 muse code coverage src/billing.py::Invoice
752 muse code coverage src/billing.py::Invoice --show-callers
753 muse code coverage src/billing.py::Invoice --json
754 ```
755
756 **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.
757
758 ---
759
760 ### `muse code deps ADDRESS_OR_FILE [OPTIONS]`
761
762 Import graph + call-graph analysis.
763
764 ```
765 muse code deps src/billing.py
766 muse code deps src/billing.py --reverse
767 muse code deps src/billing.py::compute_total
768 muse code deps src/billing.py::compute_total --reverse
769 muse code deps src/billing.py --commit v1.0 --json
770 ```
771
772 **File mode:** Lists all `import`-kind symbols from the file (what does it import?). With `--reverse`: which other files import this one.
773
774 **Symbol mode** (`address` contains `::`): Python-only call extraction — which functions does this function call? With `--reverse`: which functions call this one.
775
776 ---
777
778 ### `muse code find-symbol [OPTIONS]`
779
780 Cross-commit, cross-branch symbol search by hash, name, or kind.
781
782 ```
783 muse code find-symbol --hash a3f2c9
784 muse code find-symbol --name compute_total
785 muse code find-symbol --name compute_* --kind function
786 muse code find-symbol --hash a3f2c9 --all-branches --first
787 muse code find-symbol --name validate --json
788 ```
789
790 **Flags:**
791 - `--hash HEX` — match `content_id` prefix (exact body match across history)
792 - `--name NAME` — exact name or prefix glob with `*`
793 - `--kind KIND` — restrict to symbol kind
794 - `--all-branches` — also scan all branch tips in `.muse/refs/heads/`
795 - `--first` — deduplicate on `content_id`, keeping only the first appearance
796 - `--json` — structured output
797
798 ---
799
800 ### `muse code patch ADDRESS SOURCE [OPTIONS]`
801
802 Surgical semantic patch — replace exactly one named symbol in the working tree.
803
804 ```
805 muse code patch src/billing.py::compute_total new_impl.py
806 echo "def compute_total(x): return x * 2" | muse code patch src/billing.py::compute_total -
807 muse code patch src/billing.py::compute_total new_impl.py --dry-run
808 ```
809
810 **Syntax validation:** Before writing, validates the replacement source with:
811 - `ast.parse` for Python
812 - `tree-sitter` CST error-node check for all 11 supported languages
813
814 Rejects the patch and exits non-zero if the source has syntax errors.
815
816 **Flags:**
817 - `--dry-run` — print the unified diff without writing
818 - `--json` — structured output with patch result
819
820 ---
821
822 ## 10. Architecture Internals
823
824 ### Module Map
825
826 ```
827 muse/
828 plugins/code/
829 plugin.py MidiPlugin → CodePlugin (MuseDomainPlugin + StructuredMergePlugin)
830 ast_parser.py Python AST → SymbolRecord; validate_syntax() for all 11 languages
831 symbol_diff.py diff_symbol_trees() — O(n) diffing, rename/move annotation
832 _query.py symbols_for_snapshot(), walk_commits(), language_of()
833 _predicate.py Predicate DSL parser — tokenise → recursive descent → Predicate callable
834 _callgraph.py ForwardGraph, ReverseGraph, build_*, transitive_callers BFS
835 _refactor_classify.py classify_exact(), classify_composite(), RefactorClassification
836 core/
837 coordination.py Reservation, Intent, create/load helpers, .muse/coordination/
838 indices.py SymbolHistoryIndex, HashOccurrenceIndex, save/load/rebuild
839 ```
840
841 ### Language Support
842
843 | Language | Extension(s) | Parser | Symbol types |
844 |---|---|---|---|
845 | Python | `.py` | `ast` (stdlib) | function, async_function, class, method, variable, import |
846 | JavaScript | `.js` `.jsx` `.mjs` `.cjs` | tree-sitter | function, class, method |
847 | TypeScript | `.ts` `.tsx` | tree-sitter | function, class, method, interface, type_alias, enum |
848 | Go | `.go` | tree-sitter | function (method qualified as `Type.Method`) |
849 | Rust | `.rs` | tree-sitter | function (impl method qualified as `Type.method`) |
850 | Java | `.java` | tree-sitter | class, interface, method, constructor, enum |
851 | C | `.c` `.h` | tree-sitter | function_definition |
852 | C++ | `.cpp` `.cc` `.cxx` `.hpp` | tree-sitter | function, class, struct |
853 | C# | `.cs` | tree-sitter | class, interface, struct, method, constructor, enum |
854 | Ruby | `.rb` | tree-sitter | class, module, method, singleton_method |
855 | Kotlin | `.kt` `.kts` | tree-sitter | function, class, method |
856
857 ### Layer Rules
858
859 - `muse/core/*` is domain-agnostic — never imports from `muse/plugins/*`
860 - `muse/cli/commands/*` are thin — delegate all logic to `muse/core/*` or plugin helpers
861 - `muse/plugins/code/*` is the only layer that imports domain-specific AST logic
862 - `muse/core/coordination.py` and `muse/core/indices.py` are domain-agnostic helpers
863
864 ---
865
866 ## 11. Type Reference
867
868 ### `SymbolRecord` (TypedDict)
869
870 ```python
871 class SymbolRecord(TypedDict):
872 kind: str # function | class | method | variable | import | …
873 name: str # bare name
874 qualified_name: str # dotted path (e.g. MyClass.save)
875 lineno: int
876 end_lineno: int
877 content_id: str # SHA-256 of full normalized AST
878 body_hash: str # SHA-256 of body only
879 signature_id: str # SHA-256 of signature only
880 metadata_id: str # SHA-256 of decorators + async + bases (v2, "" for pre-v2)
881 canonical_key: str # {file}#{scope}#{kind}#{name}#{lineno} (v2, "" for pre-v2)
882 ```
883
884 ### `StructuredDelta`
885
886 ```python
887 class StructuredDelta(TypedDict):
888 domain: str
889 ops: list[DomainOp]
890 summary: str
891 sem_ver_bump: SemVerBump # default "none"
892 breaking_changes: list[str] # default []
893 ```
894
895 ### `DomainOp` union
896
897 ```python
898 DomainOp = InsertOp | DeleteOp | ReplaceOp | MoveOp | PatchOp
899 ```
900
901 Each op is a `TypedDict` discriminated by a `Literal` `"op"` field.
902
903 ### `ConflictRecord` (dataclass)
904
905 ```python
906 @dataclass
907 class ConflictRecord:
908 path: str
909 conflict_type: str = "file_level"
910 ours_summary: str = ""
911 theirs_summary: str = ""
912 addresses: list[str] = field(default_factory=list)
913 ```
914
915 ### `Reservation`
916
917 ```python
918 class Reservation:
919 reservation_id: str
920 run_id: str
921 branch: str
922 addresses: list[str]
923 created_at: datetime
924 expires_at: datetime
925 operation: str | None
926 def is_active(self) -> bool: ...
927 def to_dict(self) -> dict[str, str | int | list[str] | None]: ...
928 @classmethod
929 def from_dict(cls, d) -> Reservation: ...
930 ```
931
932 ### `Intent`
933
934 ```python
935 class Intent:
936 intent_id: str
937 reservation_id: str
938 run_id: str
939 branch: str
940 addresses: list[str]
941 operation: str
942 created_at: datetime
943 detail: str
944 def to_dict(self) -> dict[str, str | int | list[str]]: ...
945 @classmethod
946 def from_dict(cls, d) -> Intent: ...
947 ```
948
949 ### `SemVerBump`
950
951 ```python
952 SemVerBump = Literal["major", "minor", "patch", "none"]
953 ```
954
955 ### `Predicate`
956
957 ```python
958 Predicate = Callable[[str, SymbolRecord], bool]
959 # first arg: file_path
960 # second arg: SymbolRecord
961 # returns: True if the symbol matches the predicate
962 ```
963
964 ### `ExactClassification`
965
966 ```python
967 ExactClassification = Literal[
968 "rename", "move", "rename+move",
969 "signature_only", "impl_only", "metadata_only",
970 "full_rewrite", "unchanged",
971 ]
972 ```
973
974 ### `InferredRefactor`
975
976 ```python
977 InferredRefactor = Literal["extract", "inline", "split", "merge", "none"]
978 ```
979
980 ---
981
982 ## Further Reading
983
984 - [Plugin Authoring Guide](plugin-authoring-guide.md) — implementing `MuseDomainPlugin`
985 - [Type Contracts](type-contracts.md) — strict typing rules and enforcement
986 - [CRDT Reference](crdt-reference.md) — CRDT and OT merge primitives
987 - [Demo — Code](../demo/demo-code.md) — full narrative walkthrough of all code commands
988 - [Demo — MIDI](../demo/midi-demo.md) — MIDI domain demo walkthrough