gabriel / muse public
domains.md markdown
367 lines 11.2 KB
154a59f1 docs + stress tests: domains publish reference, docstrings, 13 stress/E… Gabriel Cardona <gabriel@tellurstori.com> 2d ago
1 # `muse domains` — Domain Plugin Dashboard & Marketplace Publisher
2
3 Domain plugins are the extensibility engine of Muse. Every new type of
4 multidimensional state — MIDI, source code, genomic sequences, spatial
5 scenes — is a new domain plugin. The `muse domains` command surfaces
6 the plugin registry, guides scaffold creation, and publishes plugins to
7 the [MuseHub marketplace](https://musehub.ai/domains).
8
9 ---
10
11 ## Table of Contents
12
13 1. [Overview](#overview)
14 2. [Commands](#commands)
15 - [muse domains (dashboard)](#muse-domains-dashboard)
16 - [muse domains --new](#muse-domains---new)
17 - [muse domains publish](#muse-domains-publish)
18 3. [Capability Levels](#capability-levels)
19 4. [Publishing to MuseHub](#publishing-to-musehub)
20 - [Capabilities manifest](#capabilities-manifest)
21 - [Authentication](#authentication)
22 - [HTTP semantics](#http-semantics)
23 - [Agent usage (--json)](#agent-usage---json)
24 5. [Plugin Architecture](#plugin-architecture)
25 6. [Examples](#examples)
26
27 ---
28
29 ## Overview
30
31 ```
32 muse domains # human-readable dashboard
33 muse domains --json # machine-readable registry dump
34 muse domains --new <name> # scaffold a new plugin directory
35 muse domains publish # register a plugin on MuseHub
36 ```
37
38 All four modes operate without an active Muse repository (though `publish`
39 benefits from having one — it auto-derives capability metadata from the
40 repo's active domain plugin).
41
42 ---
43
44 ## Commands
45
46 ### `muse domains` (dashboard)
47
48 Print a human-readable table of every registered domain plugin.
49
50 ```
51 ╔══════════════════════════════════════════════════════════════╗
52 ║ Muse Domain Plugin Dashboard ║
53 ╚══════════════════════════════════════════════════════════════╝
54
55 Registered domains: 2
56 ──────────────────────────────────────────────────────────────
57
58 ● midi ← active repo domain
59 Module: plugins/midi/plugin.py
60 Capabilities: Typed Deltas · Domain Schema · OT Merge
61 Schema: v0.1.3 · top_level: set · merge_mode: three_way
62 Dimensions: notes, pitch_bend, tempo_map, … (21 total)
63
64 ○ scaffold
65 Module: plugins/scaffold/plugin.py
66 Capabilities: Typed Deltas · Domain Schema · OT Merge · CRDT
67 Schema: v0.1.3 · top_level: set · merge_mode: three_way
68 Dimensions: primary, metadata
69 ──────────────────────────────────────────────────────────────
70 ```
71
72 The `●` marker identifies the active domain of the current repository.
73 `○` means registered but not active in this repo.
74
75 **Options:**
76
77 | Flag | Description |
78 |------|-------------|
79 | `--json` | Emit registry as machine-readable JSON (see [Agent usage](#agent-usage---json)) |
80
81 ---
82
83 ### `muse domains --new`
84
85 Scaffold a new domain plugin directory from the built-in scaffold template.
86
87 ```
88 muse domains --new genomics
89 ```
90
91 Creates `muse/plugins/genomics/` by copying `muse/plugins/scaffold/` and
92 renaming `ScaffoldPlugin` → `GenomicsPlugin` throughout. The scaffold
93 implements the minimal `MuseDomainPlugin` protocol so `muse domains` shows
94 it immediately.
95
96 **What gets created:**
97
98 ```
99 muse/plugins/genomics/
100 __init__.py
101 plugin.py # GenomicsPlugin implements MuseDomainPlugin
102 ```
103
104 After scaffolding, implement the six required methods in `plugin.py`:
105
106 | Method | Required | Description |
107 |--------|----------|-------------|
108 | `name()` | yes | Canonical domain name string |
109 | `diff(base, head)` | yes | Compute semantic delta |
110 | `apply(state, delta)` | yes | Apply a delta to a state |
111 | `merge(base, ours, theirs)` | yes | Three-way merge |
112 | `schema()` | recommended | Return `DomainSchema` for rich tooling |
113 | `serialize(state)` / `deserialize(blob)` | yes | Round-trip to bytes |
114
115 ---
116
117 ### `muse domains publish`
118
119 Register a Muse domain plugin on the [MuseHub marketplace](https://musehub.ai/domains)
120 so agents and users can discover and install it.
121
122 ```
123 muse domains publish \
124 --author <slug> \
125 --slug <slug> \
126 --name <display-name> \
127 --description <text> \
128 --viewer-type <type>
129 ```
130
131 **Required options:**
132
133 | Flag | Description |
134 |------|-------------|
135 | `--author SLUG` | Your MuseHub username (owner of the domain) |
136 | `--slug SLUG` | URL-safe domain identifier (e.g. `genomics`, `spatial-3d`) |
137 | `--name NAME` | Human-readable marketplace display name |
138 | `--description TEXT` | What this domain models and why it benefits from semantic VCS |
139 | `--viewer-type TYPE` | Primary viewer identifier (`midi`, `code`, `spatial`, `genome`, …) |
140
141 **Optional options:**
142
143 | Flag | Default | Description |
144 |------|---------|-------------|
145 | `--version SEMVER` | `0.1.0` | Semantic version string |
146 | `--capabilities JSON` | _(auto-derived)_ | Full capabilities manifest as JSON (see below) |
147 | `--hub URL` | `.muse/config.toml` | Override MuseHub base URL |
148 | `--json` | off | Emit server response as machine-readable JSON |
149
150 ---
151
152 ## Capability Levels
153
154 Every domain plugin is classified by the capabilities it implements:
155
156 | Capability | Protocol | Description |
157 |------------|----------|-------------|
158 | **Typed Deltas** | `MuseDomainPlugin` | Core — every domain gets this |
159 | **Domain Schema** | `schema()` method returns `DomainSchema` | Declares dimensions, merge mode, version |
160 | **OT Merge** | `StructuredMergePlugin` | Operational-transform three-way merge |
161 | **CRDT** | `CRDTPlugin` | Convergent replicated data type merge |
162
163 The dashboard shows `Typed Deltas · Domain Schema · OT Merge · CRDT` in
164 ascending capability order. These are also reflected in the `capabilities`
165 field of the published marketplace manifest.
166
167 ---
168
169 ## Publishing to MuseHub
170
171 ### Capabilities manifest
172
173 When `--capabilities` is **omitted**, the command reads the active repo's
174 domain plugin schema and derives the manifest automatically:
175
176 ```python
177 schema = plugin.schema()
178 capabilities = {
179 "dimensions": [{"name": d["name"], "description": d["description"]} for d in schema["dimensions"]],
180 "merge_semantics": schema["merge_mode"], # "three_way" or "crdt"
181 "supported_commands": ["commit", "diff", "merge", "log", "status"],
182 }
183 ```
184
185 When `--capabilities` is provided, it must be a JSON object with any
186 subset of these keys:
187
188 ```json
189 {
190 "dimensions": [
191 {"name": "geometry", "description": "3-D mesh vertex and face data"},
192 {"name": "materials", "description": "PBR material assignments"}
193 ],
194 "artifact_types": ["glb", "usdz", "obj"],
195 "merge_semantics": "three_way",
196 "supported_commands": ["commit", "diff", "merge", "log", "status"]
197 }
198 ```
199
200 ### Authentication
201
202 `muse domains publish` uses the same bearer token as `muse push`:
203
204 ```
205 muse auth login # stores token in ~/.muse/identity.toml
206 muse hub connect <url> # sets hub URL in .muse/config.toml
207 ```
208
209 The token is read by `get_auth_token()` from the hub URL configured in
210 `.muse/config.toml`. If no token is found, the command exits `1` with
211 instructions for `muse auth login`.
212
213 ### HTTP semantics
214
215 The command POSTs to `POST /api/v1/domains` on the configured MuseHub
216 instance. Possible responses:
217
218 | HTTP status | Meaning | CLI behaviour |
219 |-------------|---------|---------------|
220 | `200 OK` | Domain registered | Prints `✅ Domain published: @author/slug` |
221 | `409 Conflict` | Slug already registered | Exits `1` with "already registered" hint |
222 | `401 Unauthorized` | Invalid or expired token | Exits `1` with re-login instructions |
223 | `5xx` | Server error | Exits `1` with raw HTTP status |
224 | Network error | DNS / connection failure | Exits `1` with "Could not reach" message |
225
226 ### Agent usage (`--json`)
227
228 ```bash
229 muse domains publish \
230 --author alice --slug spatial \
231 --name "Spatial 3D" \
232 --description "Version 3-D scenes as structured state" \
233 --viewer-type spatial \
234 --json
235 ```
236
237 Output (JSON, stdout):
238
239 ```json
240 {
241 "domain_id": "dom-abc123",
242 "scoped_id": "@alice/spatial",
243 "manifest_hash": "sha256:def456..."
244 }
245 ```
246
247 Non-zero exit codes are always accompanied by a human-readable error on
248 stderr. The `--json` flag affects stdout only.
249
250 ---
251
252 ## Plugin Architecture
253
254 Every domain plugin lives under `muse/plugins/<name>/plugin.py` and
255 implements the `MuseDomainPlugin` protocol defined in `muse/domain.py`.
256
257 ```
258 muse/
259 domain.py ← MuseDomainPlugin protocol + DomainSchema type
260 plugins/
261 registry.py ← _REGISTRY: dict[str, MuseDomainPlugin]
262 midi/
263 plugin.py ← MidiPlugin (reference implementation)
264 scaffold/
265 plugin.py ← ScaffoldPlugin (copy template for new domains)
266 <your-domain>/
267 plugin.py ← YourPlugin implements MuseDomainPlugin
268 ```
269
270 The core engine in `muse/core/` **never imports** from `muse/plugins/`.
271 Domain dispatch is achieved entirely through the `MuseDomainPlugin`
272 protocol — the engine calls the six methods; it does not know or care
273 about MIDI, DNA, or spatial geometry.
274
275 **Registering a new plugin:**
276
277 ```python
278 # muse/plugins/registry.py
279 from muse.plugins.genomics.plugin import GenomicsPlugin
280
281 _REGISTRY: dict[str, MuseDomainPlugin] = {
282 "midi": MidiPlugin(),
283 "scaffold": ScaffoldPlugin(),
284 "genomics": GenomicsPlugin(), # add your plugin here
285 }
286 ```
287
288 ---
289
290 ## Examples
291
292 ### List all registered domains (machine-readable)
293
294 ```bash
295 muse domains --json | jq '.[].name'
296 ```
297
298 ### Scaffold and immediately publish a new domain
299
300 ```bash
301 # 1. Scaffold
302 muse domains --new genomics
303
304 # 2. Implement plugin.py
305 # ... implement MuseDomainPlugin methods ...
306
307 # 3. Register in muse/plugins/registry.py
308 # ... add GenomicsPlugin() to _REGISTRY ...
309
310 # 4. Publish to MuseHub
311 muse domains publish \
312 --author alice \
313 --slug genomics \
314 --name "Genomics" \
315 --description "Version DNA sequences as multidimensional state" \
316 --viewer-type genome \
317 --version 0.1.0
318 ```
319
320 ### Override capabilities for an out-of-repo publish
321
322 ```bash
323 muse domains publish \
324 --author alice \
325 --slug spatial-3d \
326 --name "Spatial 3D" \
327 --description "3-D scene version control" \
328 --viewer-type spatial \
329 --capabilities '{
330 "dimensions": [
331 {"name": "geometry", "description": "Mesh data"},
332 {"name": "materials", "description": "PBR material assignments"},
333 {"name": "lights", "description": "Light rig"}
334 ],
335 "artifact_types": ["glb", "usdz"],
336 "merge_semantics": "three_way",
337 "supported_commands": ["commit", "diff", "merge", "log"]
338 }' \
339 --json
340 ```
341
342 ### Use via agent (`musehub_publish_domain` MCP tool)
343
344 Agents do not need the CLI. MuseHub exposes `musehub_publish_domain`
345 as a first-class MCP tool:
346
347 ```json
348 {
349 "jsonrpc": "2.0",
350 "id": 1,
351 "method": "tools/call",
352 "params": {
353 "name": "musehub_publish_domain",
354 "arguments": {
355 "author_slug": "alice",
356 "slug": "genomics",
357 "display_name": "Genomics",
358 "description": "Version DNA sequences",
359 "viewer_type": "genome",
360 "version": "0.1.0"
361 }
362 }
363 }
364 ```
365
366 See [`musehub_publish_domain`](https://musehub.ai/mcp/docs#musehub_publish_domain)
367 in the MuseHub MCP reference for the full schema.