gabriel / muse public
app.py python
470 lines 26.4 KB
838d4a3e feat(omzsh-plugin): strip to minimal, secure shell integration Gabriel Cardona <gabriel@tellurstori.com> 3d ago
1 """Muse CLI — entry point for the ``muse`` console script.
2
3 Three-tier command architecture
4 --------------------------------
5
6 **Tier 1 — Plumbing** (``muse plumbing …``)
7 Machine-readable, JSON-outputting, pipeable primitives. Stable API used
8 by scripts, agents, and Tier 2 porcelain commands.
9
10 **Tier 2 — Core Porcelain** (top-level ``muse …``)
11 Human and agent VCS commands. Each command delegates business logic to
12 ``muse.core.*``; no domain-specific code lives here.
13
14 **Tier 3 — Semantic Porcelain** (``muse midi …``, ``muse code …``, ``muse coord …``)
15 Domain-specific commands that interpret multidimensional state. Each
16 sub-namespace is served by the corresponding ``muse/plugins/`` plugin.
17
18 Tier 1 — Plumbing commands::
19
20 muse plumbing hash-object SHA-256 a file; optionally store it
21 muse plumbing cat-object Emit raw bytes of a stored object
22 muse plumbing rev-parse Resolve branch/HEAD/prefix → commit_id
23 muse plumbing ls-files List tracked files and object IDs
24 muse plumbing read-commit Emit full commit JSON
25 muse plumbing read-snapshot Emit full snapshot JSON
26 muse plumbing commit-tree Create a commit from an explicit snapshot_id
27 muse plumbing update-ref Move a branch HEAD to a specific commit
28 muse plumbing commit-graph Emit commit DAG as JSON
29 muse plumbing pack-objects Build a PackBundle JSON to stdout
30 muse plumbing unpack-objects Read PackBundle JSON from stdin, write to store
31 muse plumbing ls-remote List remote branch heads
32
33 Tier 2 — Core Porcelain commands::
34
35 init status log commit diff
36 show branch checkout merge reset
37 revert stash cherry-pick tag domains
38 attributes remote clone fetch pull
39 push check annotate blame
40 reflog gc archive bisect
41 worktree workspace
42
43 Identity & hub fabric::
44
45 auth login muse auth login [--token TOKEN] [--hub HUB] [--agent]
46 auth whoami muse auth whoami [--json]
47 auth logout muse auth logout [--hub HUB]
48 hub connect muse hub connect <url>
49 hub status muse hub status [--json]
50 hub disconnect muse hub disconnect
51 hub ping muse hub ping
52 config show muse config show [--json]
53 config get muse config get <key>
54 config set muse config set <key> <value>
55 config edit muse config edit
56
57 Tier 3 — MIDI domain commands (``muse midi …``)::
58
59 Analysis:
60 notes note-log note-blame harmony piano-roll
61 hotspots velocity-profile rhythm scale contour
62 density tension cadence motif voice-leading
63 instrumentation tempo compare
64
65 Transformation:
66 transpose mix quantize humanize invert
67 retrograde arpeggiate normalize
68
69 Multi-agent & search:
70 shard agent-map find-phrase
71
72 Invariants:
73 query check
74
75 Tier 3 — Code domain commands (``muse code …``)::
76
77 symbols symbol-log detect-refactor grep
78 blame hotspots stable coupling
79 compare languages patch query
80 query-history deps find-symbol impact
81 dead coverage lineage api-surface
82 codemap clones checkout-symbol semantic-cherry-pick
83 index breakage invariants check
84
85 Tier 3 — Coordination commands (``muse coord …``)::
86
87 reserve intent forecast
88 plan-merge shard reconcile
89 """
90
91 from __future__ import annotations
92
93 import typer
94
95 from muse.cli.commands import (
96 annotate,
97 api_surface,
98 archive,
99 attributes,
100 auth,
101 bisect,
102 blame,
103 branch,
104 cherry_pick,
105 checkout,
106 checkout_symbol,
107 check,
108 clone,
109 clones,
110 codemap,
111 code_check,
112 code_query,
113 commit,
114 compare,
115 config_cmd,
116 core_blame,
117 coupling,
118 coverage,
119 dead,
120 deps,
121 detect_refactor,
122 diff,
123 domains,
124 fetch,
125 find_symbol,
126 forecast,
127 gc,
128 grep,
129 harmony,
130 hotspots,
131 hub,
132 impact,
133 index_rebuild,
134 init,
135 intent,
136 invariants,
137 languages,
138 lineage,
139 log,
140 merge,
141 mix,
142 midi_check,
143 midi_query,
144 note_blame,
145 note_hotspots,
146 note_log,
147 notes,
148 patch,
149 piano_roll,
150 plan_merge,
151 pull,
152 push,
153 query,
154 query_history,
155 reconcile,
156 reflog,
157 remote,
158 reserve,
159 reset,
160 revert,
161 semantic_cherry_pick,
162 shard,
163 show,
164 stable,
165 stash,
166 status,
167 symbol_log,
168 symbols,
169 tag,
170 breakage,
171 transpose,
172 velocity_profile,
173 worktree,
174 workspace,
175 # New MIDI semantic porcelain — analysis
176 agent_map,
177 arpeggiate,
178 cadence,
179 contour,
180 density,
181 find_phrase,
182 humanize,
183 instrumentation,
184 invert,
185 midi_compare,
186 midi_shard,
187 motif_detect,
188 quantize,
189 retrograde,
190 rhythm,
191 scale_detect,
192 tempo,
193 tension,
194 velocity_normalize,
195 voice_leading,
196 )
197 from muse.cli.commands.plumbing import (
198 cat_object,
199 commit_graph,
200 commit_tree,
201 hash_object,
202 ls_files,
203 ls_remote,
204 pack_objects,
205 read_commit,
206 read_snapshot,
207 rev_parse,
208 unpack_objects,
209 update_ref,
210 )
211
212 # ---------------------------------------------------------------------------
213 # Root CLI
214 # ---------------------------------------------------------------------------
215
216 cli = typer.Typer(
217 name="muse",
218 help="Muse — domain-agnostic version control for multidimensional state.",
219 no_args_is_help=True,
220 )
221
222 # ---------------------------------------------------------------------------
223 # Tier 1 — Plumbing sub-namespace
224 # ---------------------------------------------------------------------------
225
226 plumbing_cli = typer.Typer(
227 name="plumbing",
228 help="[Tier 1] Machine-readable plumbing commands. JSON output, pipeable, stable API.",
229 no_args_is_help=True,
230 )
231
232 plumbing_cli.add_typer(hash_object.app, name="hash-object", help="SHA-256 a file; optionally store it in the object store.")
233 plumbing_cli.add_typer(cat_object.app, name="cat-object", help="Emit raw bytes of a stored object to stdout.")
234 plumbing_cli.add_typer(rev_parse.app, name="rev-parse", help="Resolve branch/HEAD/SHA prefix → full commit_id.")
235 plumbing_cli.add_typer(ls_files.app, name="ls-files", help="List all tracked files and their object IDs in a snapshot.")
236 plumbing_cli.add_typer(read_commit.app, name="read-commit", help="Emit full commit metadata as JSON.")
237 plumbing_cli.add_typer(read_snapshot.app, name="read-snapshot", help="Emit full snapshot metadata and manifest as JSON.")
238 plumbing_cli.add_typer(commit_tree.app, name="commit-tree", help="Create a commit from an explicit snapshot ID.")
239 plumbing_cli.add_typer(update_ref.app, name="update-ref", help="Move a branch HEAD to a specific commit ID.")
240 plumbing_cli.add_typer(commit_graph.app, name="commit-graph", help="Emit the commit DAG as a JSON node list.")
241 plumbing_cli.add_typer(pack_objects.app, name="pack-objects", help="Build a PackBundle JSON from wanted commits and write to stdout.")
242 plumbing_cli.add_typer(unpack_objects.app, name="unpack-objects", help="Read a PackBundle JSON from stdin and write to the local store.")
243 plumbing_cli.add_typer(ls_remote.app, name="ls-remote", help="List branch heads on a remote without modifying local state.")
244
245 cli.add_typer(plumbing_cli, name="plumbing")
246
247 # ---------------------------------------------------------------------------
248 # Tier 2 — Core Porcelain (top-level VCS commands)
249 # ---------------------------------------------------------------------------
250
251 cli.add_typer(attributes.app, name="attributes", help="Display .museattributes merge-strategy rules.")
252 cli.add_typer(init.app, name="init", help="Initialise a new Muse repository.")
253
254 # Identity & hub fabric
255 cli.add_typer(auth.app, name="auth", help="Identity management — login as human or agent, inspect credentials.")
256 cli.add_typer(hub.app, name="hub", help="MuseHub fabric — connect, inspect, and disconnect this repo from the hub.")
257 cli.add_typer(config_cmd.app, name="config", help="Local repository configuration — show, get, set typed config values.")
258
259 # Remote sync
260 cli.add_typer(remote.app, name="remote", help="Manage remote repository connections (add, remove, rename, list).")
261 cli.add_typer(clone.app, name="clone", help="Create a local copy of a remote Muse repository.")
262 cli.add_typer(fetch.app, name="fetch", help="Download commits, snapshots, and objects from a remote.")
263 cli.add_typer(pull.app, name="pull", help="Fetch from a remote and merge into the current branch.")
264 cli.add_typer(push.app, name="push", help="Upload local commits, snapshots, and objects to a remote.")
265
266 # Core VCS
267 cli.add_typer(commit.app, name="commit", help="Record the current working tree as a new version.")
268 cli.add_typer(status.app, name="status", help="Show working-tree drift against HEAD.")
269 cli.add_typer(log.app, name="log", help="Display commit history.")
270 cli.add_typer(diff.app, name="diff", help="Compare working tree against HEAD, or two commits.")
271 cli.add_typer(show.app, name="show", help="Inspect a commit: metadata, diff, files.")
272 cli.add_typer(branch.app, name="branch", help="List, create, or delete branches.")
273 cli.add_typer(checkout.app, name="checkout", help="Switch branches or restore working tree from a commit.")
274 cli.add_typer(merge.app, name="merge", help="Three-way merge a branch into the current branch.")
275 cli.add_typer(reset.app, name="reset", help="Move HEAD to a prior commit.")
276 cli.add_typer(revert.app, name="revert", help="Create a new commit that undoes a prior commit.")
277 cli.add_typer(cherry_pick.app, name="cherry-pick", help="Apply a specific commit's changes on top of HEAD.")
278 cli.add_typer(stash.app, name="stash", help="Shelve and restore uncommitted changes.")
279 cli.add_typer(tag.app, name="tag", help="Attach and query semantic tags on commits.")
280 cli.add_typer(domains.app, name="domains", help="Domain plugin dashboard — list capabilities and scaffold new domains.")
281
282 # Cross-domain
283 cli.add_typer(check.app, name="check", help="[*] Domain-agnostic invariant check — dispatches to the active domain plugin.")
284 cli.add_typer(annotate.app, name="annotate", help="[*] CRDT-backed commit annotations — reviewed-by (ORSet) and test-run counter (GCounter).")
285
286 # VCS completeness — safety net, search, export, multi-repo
287 cli.add_typer(core_blame.app, name="blame", help="Line-level attribution for any text file — which commit last changed each line.")
288 cli.add_typer(reflog.app, name="reflog", help="Show the history of HEAD and branch-ref movements — the undo safety net.")
289 cli.add_typer(gc.app, name="gc", help="Garbage-collect unreachable objects from the object store.")
290 cli.add_typer(archive.app, name="archive", help="Export any historical snapshot as a portable tar.gz or zip archive.")
291 cli.add_typer(bisect.app, name="bisect", help="Binary search through commit history to isolate the first bad commit.")
292 cli.add_typer(worktree.app, name="worktree", help="Manage multiple simultaneous branch checkouts (one state/ per branch).")
293 cli.add_typer(workspace.app, name="workspace", help="Compose and manage multi-repository workspaces.")
294
295 # ---------------------------------------------------------------------------
296 # Tier 3 — MIDI domain semantic commands (muse midi …)
297 # ---------------------------------------------------------------------------
298
299 midi_cli = typer.Typer(
300 name="midi",
301 help="[Tier 3] MIDI domain semantic commands — music-aware version control operations.",
302 no_args_is_help=True,
303 )
304
305 midi_cli.add_typer(notes.app, name="notes", help="List every note in a MIDI track as musical notation.")
306 midi_cli.add_typer(note_log.app, name="note-log", help="Note-level commit history — which notes were added or removed in each commit.")
307 midi_cli.add_typer(note_blame.app, name="note-blame", help="Per-bar attribution — which commit introduced the notes in this bar?")
308 midi_cli.add_typer(harmony.app, name="harmony", help="Chord analysis and key detection from MIDI note content.")
309 midi_cli.add_typer(piano_roll.app, name="piano-roll", help="ASCII piano roll visualization of a MIDI track.")
310 midi_cli.add_typer(note_hotspots.app, name="hotspots", help="Bar-level churn leaderboard — which bars change most across commits.")
311 midi_cli.add_typer(velocity_profile.app, name="velocity-profile", help="Dynamic range and velocity histogram for a MIDI track.")
312 midi_cli.add_typer(transpose.app, name="transpose", help="Transpose all notes in a MIDI track by N semitones.")
313 midi_cli.add_typer(mix.app, name="mix", help="Combine notes from two MIDI tracks into a single output track.")
314 midi_cli.add_typer(midi_query.app, name="query", help="MIDI DSL predicate query over commit history — bars, chords, agents, pitches.")
315 midi_cli.add_typer(midi_check.app, name="check", help="Enforce MIDI invariant rules (polyphony, pitch range, key consistency, parallel fifths).")
316 # --- Analysis porcelain ---
317 midi_cli.add_typer(rhythm.app, name="rhythm", help="Quantify syncopation, swing ratio, and quantisation accuracy of a MIDI track.")
318 midi_cli.add_typer(scale_detect.app, name="scale", help="Detect scale or mode (major, dorian, blues, whole-tone…) from pitch-class analysis.")
319 midi_cli.add_typer(contour.app, name="contour", help="Classify melodic contour shape (arch, ascending, wave…) and report interval sequence.")
320 midi_cli.add_typer(density.app, name="density", help="Note density (notes per beat) per bar — reveals textural arc of a composition.")
321 midi_cli.add_typer(tension.app, name="tension", help="Harmonic tension curve per bar — consonance/dissonance arc from interval dissonance weights.")
322 midi_cli.add_typer(cadence.app, name="cadence", help="Detect phrase-ending cadences (authentic, deceptive, half, plagal) at bar boundaries.")
323 midi_cli.add_typer(motif_detect.app, name="motif", help="Find recurring melodic interval patterns (motifs) in a MIDI track.")
324 midi_cli.add_typer(voice_leading.app, name="voice-leading", help="Detect parallel fifths, octaves, and large leaps — classical voice-leading lint.")
325 midi_cli.add_typer(instrumentation.app, name="instrumentation", help="Per-channel note distribution, pitch range, register, and velocity map.")
326 midi_cli.add_typer(tempo.app, name="tempo", help="Estimate BPM from inter-onset intervals; report ticks-per-beat metadata.")
327 midi_cli.add_typer(midi_compare.app, name="compare", help="Semantic comparison between two MIDI snapshots across key, rhythm, density, and swing.")
328 # --- Transformation porcelain ---
329 midi_cli.add_typer(quantize.app, name="quantize", help="Snap note onsets to a rhythmic grid (16th, 8th, triplet, …) with adjustable strength.")
330 midi_cli.add_typer(humanize.app, name="humanize", help="Add subtle timing and velocity variation to give quantised MIDI a human feel.")
331 midi_cli.add_typer(invert.app, name="invert", help="Melodic inversion — reflect all intervals around a pivot pitch.")
332 midi_cli.add_typer(retrograde.app, name="retrograde", help="Retrograde transformation — reverse the pitch order of all notes.")
333 midi_cli.add_typer(arpeggiate.app, name="arpeggiate", help="Convert simultaneous chord voicings into a sequential arpeggio pattern.")
334 midi_cli.add_typer(velocity_normalize.app, name="normalize", help="Rescale note velocities to a target dynamic range [min, max].")
335 # --- Multi-agent & search porcelain ---
336 midi_cli.add_typer(midi_shard.app, name="shard", help="Partition a MIDI composition into bar-range shards for parallel agent work.")
337 midi_cli.add_typer(agent_map.app, name="agent-map", help="Show which agent last edited each bar of a MIDI track (bar-level blame).")
338 midi_cli.add_typer(find_phrase.app, name="find-phrase", help="Search for a melodic phrase across MIDI commit history by similarity scoring.")
339
340 cli.add_typer(midi_cli, name="midi")
341
342 # ---------------------------------------------------------------------------
343 # Tier 3 — Code domain semantic commands (muse code …)
344 # ---------------------------------------------------------------------------
345
346 code_cli = typer.Typer(
347 name="code",
348 help="[Tier 3] Code domain semantic commands — symbol graph, call graph, and provenance.",
349 no_args_is_help=True,
350 )
351
352 code_cli.add_typer(symbols.app, name="symbols", help="List every semantic symbol (function, class, method…) in a snapshot.")
353 code_cli.add_typer(symbol_log.app, name="symbol-log", help="Track a single symbol through the full commit history.")
354 code_cli.add_typer(detect_refactor.app, name="detect-refactor", help="Detect semantic refactoring operations (renames, moves, extractions) across commits.")
355 code_cli.add_typer(grep.app, name="grep", help="Search the symbol graph by name, kind, or language — not file text.")
356 code_cli.add_typer(blame.app, name="blame", help="Show which commit last touched a specific symbol (function, class, method).")
357 code_cli.add_typer(hotspots.app, name="hotspots", help="Symbol churn leaderboard — which functions change most often.")
358 code_cli.add_typer(stable.app, name="stable", help="Symbol stability leaderboard — the bedrock of your codebase.")
359 code_cli.add_typer(coupling.app, name="coupling", help="File co-change analysis — discover hidden semantic dependencies.")
360 code_cli.add_typer(compare.app, name="compare", help="Deep semantic comparison between any two historical snapshots.")
361 code_cli.add_typer(languages.app, name="languages", help="Language and symbol-type breakdown of a snapshot.")
362 code_cli.add_typer(patch.app, name="patch", help="Surgical semantic patch — modify exactly one named symbol (all-language syntax validation).")
363 code_cli.add_typer(query.app, name="query", help="Symbol graph predicate DSL — OR/NOT/grouping, --all-commits temporal search.")
364 code_cli.add_typer(query_history.app, name="query-history", help="Temporal symbol search — first seen, last seen, change count across a commit range.")
365 code_cli.add_typer(deps.app, name="deps", help="Import graph + Python call-graph; --reverse for callers/importers.")
366 code_cli.add_typer(find_symbol.app, name="find-symbol", help="Cross-commit, cross-branch symbol search by hash, name, or kind.")
367 code_cli.add_typer(impact.app, name="impact", help="Transitive blast-radius — every caller affected if this symbol changes.")
368 code_cli.add_typer(dead.app, name="dead", help="Dead code candidates — symbols with no callers and no importers.")
369 code_cli.add_typer(coverage.app, name="coverage", help="Class interface call-coverage — which methods are actually called?")
370 code_cli.add_typer(lineage.app, name="lineage", help="Full provenance chain of a symbol — created, renamed, moved, copied, deleted.")
371 code_cli.add_typer(api_surface.app, name="api-surface", help="Public API surface at a commit; --diff to show added/removed/changed symbols.")
372 code_cli.add_typer(codemap.app, name="codemap", help="Semantic topology — module sizes, import cycles, centrality, boundary files.")
373 code_cli.add_typer(clones.app, name="clones", help="Find exact and near-duplicate symbols (body_hash / signature_id clusters).")
374 code_cli.add_typer(checkout_symbol.app, name="checkout-symbol", help="Restore a historical version of one symbol into the working tree.")
375 code_cli.add_typer(semantic_cherry_pick.app, name="semantic-cherry-pick", help="Cherry-pick named symbols from a historical commit into the working tree.")
376 code_cli.add_typer(index_rebuild.app, name="index", help="Manage local indexes: status, rebuild symbol_history / hash_occurrence.")
377 code_cli.add_typer(breakage.app, name="breakage", help="Detect symbol-level structural breakage in the working tree vs HEAD.")
378 code_cli.add_typer(invariants.app, name="invariants", help="Enforce architectural rules from .muse/invariants.toml.")
379 code_cli.add_typer(code_check.app, name="check", help="Semantic invariant enforcement — complexity, import cycles, dead exports, test coverage.")
380 code_cli.add_typer(code_query.app, name="code-query", help="Predicate query over code commit history — symbol, file, language, agent_id, sem_ver_bump.")
381
382 cli.add_typer(code_cli, name="code")
383
384 # ---------------------------------------------------------------------------
385 # Tier 3 — Multi-agent coordination commands (muse coord …)
386 # ---------------------------------------------------------------------------
387
388 coord_cli = typer.Typer(
389 name="coord",
390 help="[Tier 3] Multi-agent coordination commands — reservations, intent, conflict forecasting.",
391 no_args_is_help=True,
392 )
393
394 coord_cli.add_typer(reserve.app, name="reserve", help="Advisory symbol reservation — announce intent before editing.")
395 coord_cli.add_typer(intent.app, name="intent", help="Declare a specific operation before executing it.")
396 coord_cli.add_typer(forecast.app, name="forecast", help="Predict merge conflicts from active reservations and intents.")
397 coord_cli.add_typer(plan_merge.app, name="plan-merge", help="Dry-run semantic merge plan — classify conflicts without writing.")
398 coord_cli.add_typer(shard.app, name="shard", help="Partition the codebase into N low-coupling work zones for parallel agents.")
399 coord_cli.add_typer(reconcile.app, name="reconcile", help="Recommend merge ordering and integration strategy from coordination state.")
400
401 cli.add_typer(coord_cli, name="coord")
402
403 # ---------------------------------------------------------------------------
404 # Tier 3 — Bitcoin domain semantic commands (muse bitcoin …)
405 # ---------------------------------------------------------------------------
406
407 from muse.cli.commands import ( # noqa: E402
408 btc_balance,
409 btc_check,
410 btc_compare,
411 btc_consolidate,
412 btc_dust,
413 btc_fee,
414 btc_halving,
415 btc_hodl,
416 btc_mempool,
417 btc_moon,
418 btc_oracle,
419 btc_pnl,
420 btc_privacy,
421 btc_provenance,
422 btc_select_coins,
423 btc_stack,
424 btc_strategy,
425 btc_utxos,
426 btc_whale,
427 )
428
429 bitcoin_cli = typer.Typer(
430 name="bitcoin",
431 help="[Tier 3] Bitcoin domain semantic commands — on-chain UTXO analytics, coin selection, and agent strategy.",
432 no_args_is_help=True,
433 )
434
435 # --- Wallet & balance ---
436 bitcoin_cli.add_typer(btc_balance.app, name="balance", help="On-chain balance: confirmed, unconfirmed, by script type and category, USD value.")
437 bitcoin_cli.add_typer(btc_utxos.app, name="utxos", help="Full UTXO set with lifecycle analysis: age, effective value, dust flag, label.")
438
439 # --- Bitcoin-culture commands ---
440 bitcoin_cli.add_typer(btc_hodl.app, name="hodl", help="HODL score, diamond-hands analysis, and age distribution of the UTXO stack.")
441 bitcoin_cli.add_typer(btc_whale.app, name="whale", help="Whale-tier classification (Plankton → Humpback) and tier-progression ladder.")
442 bitcoin_cli.add_typer(btc_moon.app, name="moon", help="Portfolio value at price targets — to the moon and beyond.")
443 bitcoin_cli.add_typer(btc_halving.app, name="halving", help="Halving epoch, current block subsidy, and countdown to the next supply event.")
444 bitcoin_cli.add_typer(btc_stack.app, name="stack", help="Stacking-sats accumulation history: balance delta across commit history.")
445
446 # --- Fee & mempool ---
447 bitcoin_cli.add_typer(btc_fee.app, name="fee", help="Fee-market window: current rate vs history, percentile, send-now / wait / RBF recommendation.")
448 bitcoin_cli.add_typer(btc_mempool.app, name="mempool", help="Pending transactions with fee rate and RBF flags.")
449
450 # --- Coin management ---
451 bitcoin_cli.add_typer(btc_select_coins.app, name="select-coins", help="Agent-first coin selection: BnB / largest / smallest / random, dust excluded.")
452 bitcoin_cli.add_typer(btc_consolidate.app, name="consolidate", help="UTXO consolidation planner: fee cost, savings, break-even analysis.")
453 bitcoin_cli.add_typer(btc_dust.app, name="dust", help="Dust UTXO analysis: unspendable coins, total locked value, cleanup recommendations.")
454
455 # --- Analytics & history ---
456 bitcoin_cli.add_typer(btc_pnl.app, name="pnl", help="Portfolio P&L between two commits: sat delta and oracle-anchored USD delta.")
457 bitcoin_cli.add_typer(btc_compare.app, name="compare", help="Deep semantic comparison between two snapshots: received, spent, strategy changes.")
458 bitcoin_cli.add_typer(btc_provenance.app, name="provenance", help="UTXO lineage through the MUSE commit DAG — appeared, held, and spent events.")
459
460 # --- Agent & strategy ---
461 bitcoin_cli.add_typer(btc_strategy.app, name="strategy", help="Active agent strategy config with optional diff against a historical commit.")
462 bitcoin_cli.add_typer(btc_oracle.app, name="oracle", help="Versioned price and fee oracle history with trend analysis.")
463 bitcoin_cli.add_typer(btc_check.app, name="check", help="Enforce Bitcoin state invariants: maturity, fee ceiling, address reuse, strategy sanity.")
464 bitcoin_cli.add_typer(btc_privacy.app, name="privacy", help="Privacy analysis: address reuse, script-type entropy, Taproot adoption.")
465
466 cli.add_typer(bitcoin_cli, name="bitcoin")
467
468
469 if __name__ == "__main__":
470 cli()