cgcardona / muse public
cli-tiers.md markdown
410 lines 14.3 KB
1f0a7cd9 docs: rename demo-midi.md → midi-demo.md and add full MIDI domain reference Gabriel Cardona <gabriel@tellurstori.com> 15h ago
1 # Muse CLI — Three-Tier Architecture Reference
2
3 Muse CLI is organized into three formally separated tiers. Each tier has a
4 distinct contract, audience, and stability guarantee.
5
6 ```
7 ┌──────────────────────────────────────────────────────────────────┐
8 │ Tier 3 — Semantic Porcelain │
9 │ muse midi … muse code … muse coord … │
10 │ Domain-specific multidimensional commands │
11 ├──────────────────────────────────────────────────────────────────┤
12 │ Tier 2 — Core Porcelain │
13 │ muse init / commit / status / log / diff / show … │
14 │ Human and agent VCS operations (domain-agnostic) │
15 ├──────────────────────────────────────────────────────────────────┤
16 │ Tier 1 — Plumbing │
17 │ muse plumbing hash-object / cat-object / rev-parse … │
18 │ Machine-readable, JSON-outputting, pipeable primitives │
19 └──────────────────────────────────────────────────────────────────┘
20 ```
21
22 ---
23
24 ## Tier 1 — Plumbing
25
26 **Namespace:** `muse plumbing <command>`
27
28 ### Contract
29
30 Every Tier 1 command:
31
32 - **Outputs JSON by default** — machine-stable schema, versioned, agent-parseable.
33 - **Accepts `--format text`** — human-readable fallback where meaningful.
34 - **Never prompts** — strictly non-interactive; safe for agent pipelines.
35 - **Exit codes** — `0` success, `1` user error (bad args, missing ref), `3` internal error.
36 - **Pipeable** — reads from stdin (`unpack-objects`) or writes to stdout (`pack-objects`, `cat-object`).
37 - **Stable API** — output schemas do not break across Muse versions.
38
39 Tier 1 commands are the atoms from which Tier 2 porcelain is composed. They
40 expose the raw engine directly, enabling MuseHub, agent orchestrators, CI
41 pipelines, and shell scripts to interact with the store without going through
42 the higher-level VCS logic.
43
44 ### Commands
45
46 | Command | Description |
47 |---------|-------------|
48 | `muse plumbing hash-object [--write] <file>` | SHA-256 a file; optionally store it in `.muse/objects/` |
49 | `muse plumbing cat-object [--format raw\|info] <object_id>` | Emit raw bytes of a stored blob to stdout |
50 | `muse plumbing rev-parse [--format json\|text] <ref>` | Resolve branch / HEAD / SHA prefix → full commit ID |
51 | `muse plumbing ls-files [--commit <id>] [--format json\|text]` | List all tracked files and their object IDs |
52 | `muse plumbing read-commit <id>` | Emit full commit metadata as JSON |
53 | `muse plumbing read-snapshot <id>` | Emit full snapshot manifest and metadata as JSON |
54 | `muse plumbing commit-tree --snapshot <id> [--parent <id>]… [--message <msg>]` | Create a commit from an explicit snapshot ID |
55 | `muse plumbing update-ref [--delete\|--no-verify] <branch> [<commit_id>]` | Move or delete a branch HEAD |
56 | `muse plumbing commit-graph [--tip <id>] [--stop-at <id>] [--max N]` | Emit the commit DAG as a JSON node list |
57 | `muse plumbing pack-objects [--have <id>]… <want_id>…` | Build a `PackBundle` JSON and write to stdout |
58 | `muse plumbing unpack-objects` | Read `PackBundle` JSON from stdin, write to local store |
59 | `muse plumbing ls-remote [--json] <remote-or-url>` | List remote branch heads without modifying local state |
60
61 ### JSON Output Schemas
62
63 #### `hash-object`
64
65 ```json
66 {
67 "object_id": "<sha256-hex-64>",
68 "stored": false
69 }
70 ```
71
72 #### `cat-object --format info`
73
74 ```json
75 {
76 "object_id": "<sha256-hex-64>",
77 "present": true,
78 "size_bytes": 1234
79 }
80 ```
81
82 With `--format raw` (default): raw bytes written to stdout.
83
84 #### `rev-parse`
85
86 ```json
87 {
88 "ref": "main",
89 "commit_id": "<sha256-hex-64>"
90 }
91 ```
92
93 Error (exit 1):
94 ```json
95 {
96 "ref": "nonexistent",
97 "commit_id": null,
98 "error": "not found"
99 }
100 ```
101
102 #### `ls-files`
103
104 ```json
105 {
106 "commit_id": "<sha256>",
107 "snapshot_id": "<sha256>",
108 "file_count": 3,
109 "files": [
110 {"path": "tracks/drums.mid", "object_id": "<sha256>"},
111 {"path": "tracks/bass.mid", "object_id": "<sha256>"}
112 ]
113 }
114 ```
115
116 #### `read-commit`
117
118 Full `CommitRecord` JSON — see `store.py` for the complete schema.
119 Key fields:
120
121 ```json
122 {
123 "commit_id": "<sha256>",
124 "repo_id": "<uuid>",
125 "branch": "main",
126 "snapshot_id": "<sha256>",
127 "message": "Add verse melody",
128 "committed_at": "2026-03-18T12:00:00+00:00",
129 "parent_commit_id": "<sha256> | null",
130 "parent2_commit_id": null,
131 "author": "gabriel",
132 "agent_id": "",
133 "sem_ver_bump": "none"
134 }
135 ```
136
137 #### `read-snapshot`
138
139 ```json
140 {
141 "snapshot_id": "<sha256>",
142 "created_at": "2026-03-18T12:00:00+00:00",
143 "file_count": 3,
144 "manifest": {
145 "tracks/drums.mid": "<sha256>",
146 "tracks/bass.mid": "<sha256>"
147 }
148 }
149 ```
150
151 #### `commit-tree`
152
153 ```json
154 {"commit_id": "<sha256>"}
155 ```
156
157 #### `update-ref`
158
159 ```json
160 {
161 "branch": "main",
162 "commit_id": "<sha256>",
163 "previous": "<sha256> | null"
164 }
165 ```
166
167 Delete (`--delete`):
168 ```json
169 {"branch": "todelete", "deleted": true}
170 ```
171
172 #### `commit-graph`
173
174 ```json
175 {
176 "tip": "<sha256>",
177 "count": 42,
178 "truncated": false,
179 "commits": [
180 {
181 "commit_id": "<sha256>",
182 "parent_commit_id": "<sha256> | null",
183 "parent2_commit_id": null,
184 "message": "Add verse melody",
185 "branch": "main",
186 "committed_at": "2026-03-18T12:00:00+00:00",
187 "snapshot_id": "<sha256>",
188 "author": "gabriel"
189 }
190 ]
191 }
192 ```
193
194 #### `pack-objects` / `unpack-objects`
195
196 `pack-objects` writes a `PackBundle` JSON to stdout:
197
198 ```json
199 {
200 "commits": [{ ...CommitDict... }],
201 "snapshots": [{ ...SnapshotDict... }],
202 "objects": [{"object_id": "<sha256>", "content_b64": "<base64>"}],
203 "branch_heads": {"main": "<sha256>"}
204 }
205 ```
206
207 `unpack-objects` reads a `PackBundle` from stdin and outputs:
208
209 ```json
210 {
211 "commits_written": 12,
212 "snapshots_written": 12,
213 "objects_written": 47,
214 "objects_skipped": 3
215 }
216 ```
217
218 #### `ls-remote --json`
219
220 ```json
221 {
222 "repo_id": "<uuid>",
223 "domain": "midi",
224 "default_branch": "main",
225 "branches": {
226 "main": "<sha256>",
227 "dev": "<sha256>"
228 }
229 }
230 ```
231
232 ---
233
234 ## Tier 2 — Core Porcelain
235
236 **Namespace:** top-level `muse <command>`
237
238 These are the human and agent VCS commands — the interface most users interact
239 with. They compose Tier 1 plumbing primitives into user-friendly workflows.
240
241 | Command | Description |
242 |---------|-------------|
243 | `muse init` | Initialise a new Muse repository |
244 | `muse commit` | Record the current working tree as a new version |
245 | `muse status` | Show working-tree drift against HEAD |
246 | `muse log` | Display commit history |
247 | `muse diff` | Compare working tree against HEAD, or two commits |
248 | `muse show` | Inspect a commit: metadata, diff, files |
249 | `muse branch` | List, create, or delete branches |
250 | `muse checkout` | Switch branches or restore working tree |
251 | `muse merge` | Three-way merge a branch into the current branch |
252 | `muse reset` | Move HEAD to a prior commit |
253 | `muse revert` | Create a commit that undoes a prior commit |
254 | `muse cherry-pick` | Apply a specific commit's changes on top of HEAD |
255 | `muse stash` | Shelve and restore uncommitted changes |
256 | `muse tag` | Attach and query semantic tags on commits |
257 | `muse domains` | Domain plugin dashboard |
258 | `muse attributes` | Display `.museattributes` merge-strategy rules |
259 | `muse remote` | Manage remote connections (add/remove/list/set-url) |
260 | `muse clone` | Create a local copy of a remote Muse repository |
261 | `muse fetch` | Download commits/snapshots/objects from a remote |
262 | `muse pull` | Fetch from a remote and merge into current branch |
263 | `muse push` | Upload local commits/snapshots/objects to a remote |
264 | `muse check` | Domain-agnostic invariant check |
265 | `muse annotate` | CRDT-backed commit annotations |
266
267 ---
268
269 ## Tier 3 — Semantic Porcelain
270
271 **Namespaces:** `muse midi …`, `muse code …`, `muse coord …`
272
273 Domain-specific commands that interpret multidimensional state. These are
274 impossible to implement in Git — they require awareness of the domain's
275 semantic model (note events, symbol graphs, agent coordination).
276
277 ### `muse midi …` — MIDI Domain
278
279 Full reference: [MIDI Domain Reference](midi-domain.md)
280
281 **Notation & Visualization**
282
283 | Command | Description |
284 |---------|-------------|
285 | `muse midi notes` | List every note in a MIDI track as musical notation |
286 | `muse midi piano-roll` | ASCII piano roll visualization |
287 | `muse midi instrumentation` | Per-channel note range, register, and velocity map |
288
289 **Pitch, Harmony & Scale**
290
291 | Command | Description |
292 |---------|-------------|
293 | `muse midi harmony` | Bar-by-bar chord detection and key signature estimation |
294 | `muse midi scale` | Scale/mode detection: 15 types × 12 roots, ranked by confidence |
295 | `muse midi contour` | Melodic contour shape and interval sequence |
296 | `muse midi tension` | Harmonic tension curve: dissonance score per bar |
297 | `muse midi cadence` | Cadence detection: authentic, deceptive, half, plagal |
298
299 **Rhythm & Dynamics**
300
301 | Command | Description |
302 |---------|-------------|
303 | `muse midi rhythm` | Syncopation score, swing ratio, quantisation accuracy, subdivision |
304 | `muse midi tempo` | BPM estimation via IOI voting; confidence rated |
305 | `muse midi density` | Notes-per-beat per bar — textural arc of a composition |
306 | `muse midi velocity-profile` | Dynamic range, RMS velocity, and histogram (ppp–fff) |
307
308 **Structure & Voice Leading**
309
310 | Command | Description |
311 |---------|-------------|
312 | `muse midi motif` | Recurring interval-pattern detection, transposition-invariant |
313 | `muse midi voice-leading` | Parallel fifths/octaves + large leaps — counterpoint lint |
314 | `muse midi compare` | Semantic diff across key, rhythm, density, swing between two commits |
315
316 **History & Attribution**
317
318 | Command | Description |
319 |---------|-------------|
320 | `muse midi note-log` | Note-level commit history |
321 | `muse midi note-blame` | Per-bar attribution: which commit introduced each note |
322 | `muse midi hotspots` | Bar-level churn leaderboard |
323
324 **Multi-Agent Intelligence**
325
326 | Command | Description |
327 |---------|-------------|
328 | `muse midi agent-map` | Bar-level blame: which agent last edited each bar |
329 | `muse midi find-phrase` | Phrase similarity search across commit history |
330 | `muse midi shard` | Partition composition into N bar-range shards for parallel agents |
331 | `muse midi query` | MIDI DSL predicate query over note data and commit history |
332
333 **Transformation**
334
335 | Command | Description |
336 |---------|-------------|
337 | `muse midi transpose` | Shift all pitches by N semitones |
338 | `muse midi invert` | Melodic inversion around a pivot pitch |
339 | `muse midi retrograde` | Reverse pitch order (retrograde transformation) |
340 | `muse midi quantize` | Snap onsets to a rhythmic grid with adjustable strength |
341 | `muse midi humanize` | Add timing/velocity jitter for human feel |
342 | `muse midi arpeggiate` | Convert chord voicings to arpeggios |
343 | `muse midi normalize` | Rescale velocities to a target dynamic range |
344 | `muse midi mix` | Combine notes from two MIDI tracks into one output file |
345
346 **Invariants & Quality Gates**
347
348 | Command | Description |
349 |---------|-------------|
350 | `muse midi check` | Enforce MIDI invariant rules (CI gate) |
351
352 ### `muse code …` — Code Domain
353
354 | Command | Description |
355 |---------|-------------|
356 | `muse code symbols` | List every semantic symbol in a snapshot |
357 | `muse code symbol-log` | Track a symbol through commit history |
358 | `muse code detect-refactor` | Detect renames, moves, extractions |
359 | `muse code grep` | Search the symbol graph by name/kind/language |
360 | `muse code blame` | Which commit last touched a specific symbol? |
361 | `muse code hotspots` | Symbol churn leaderboard |
362 | `muse code stable` | Symbol stability leaderboard |
363 | `muse code coupling` | File co-change analysis |
364 | `muse code compare` | Deep semantic comparison between snapshots |
365 | `muse code languages` | Language and symbol-type breakdown |
366 | `muse code patch` | Surgical semantic patch on a single symbol |
367 | `muse code query` | Symbol graph predicate DSL |
368 | `muse code query-history` | Temporal symbol search across a commit range |
369 | `muse code deps` | Import graph + call-graph |
370 | `muse code find-symbol` | Cross-commit, cross-branch symbol search |
371 | `muse code impact` | Transitive blast-radius |
372 | `muse code dead` | Dead code candidates |
373 | `muse code coverage` | Class interface call-coverage |
374 | `muse code lineage` | Full provenance chain of a symbol |
375 | `muse code api-surface` | Public API surface at a commit |
376 | `muse code codemap` | Semantic topology |
377 | `muse code clones` | Exact and near-duplicate symbols |
378 | `muse code checkout-symbol` | Restore a historical version of one symbol |
379 | `muse code semantic-cherry-pick` | Cherry-pick named symbols from a commit |
380 | `muse code index` | Manage local indexes |
381 | `muse code breakage` | Detect symbol-level structural breakage |
382 | `muse code invariants` | Enforce architectural rules |
383 | `muse code check` | Semantic invariant enforcement |
384 | `muse code code-query` | Predicate query over code commit history |
385
386 ### `muse coord …` — Multi-Agent Coordination
387
388 | Command | Description |
389 |---------|-------------|
390 | `muse coord reserve` | Advisory symbol reservation |
391 | `muse coord intent` | Declare a specific operation before executing it |
392 | `muse coord forecast` | Predict merge conflicts |
393 | `muse coord plan-merge` | Dry-run semantic merge plan |
394 | `muse coord shard` | Partition the codebase into N work zones |
395 | `muse coord reconcile` | Recommend merge ordering and integration strategy |
396
397 ---
398
399 ## Extending with New Domains
400
401 To add a new domain (e.g. `muse genomics …`):
402
403 1. Create `muse/plugins/genomics/plugin.py` implementing `MuseDomainPlugin`.
404 2. Create `muse/cli/commands/genomics_*.py` command modules.
405 3. Add a `genomics_cli = typer.Typer(name="genomics", …)` in `muse/cli/app.py`.
406 4. Register commands under `genomics_cli` and add `cli.add_typer(genomics_cli, name="genomics")`.
407 5. Write tests under `tests/` and docs under `docs/reference/`.
408
409 The core engine (`muse/core/`) is **never modified** for a new domain.
410