# Lumbridge Compute Scene Spec (`lumbridge/v1`) This is the public contract. Everything else — the Governor, the CLI, the scheduler — can be refactored freely. This format cannot, once people publish scenes against it. So it is deliberately small. ## The core idea: scenes reference ids, not weights A **scene** is a manifest listing **model ids**. A **model registry** resolves each id to actual weights + a launch command. The registry churns as models evolve (new quants, new backends, bigger context); the scene stays stable. ``` scene (stable, shareable) registry (local, evolves) ───────────────────────── ────────────────────────────── models: [ears, brain, voice] ──▶ brain → ~/models/Qwen3.6-35B-A3B-NVFP4-Fast → vllm serve, gmu 0.55, flashinfer... ``` This is the same decoupling the original harness used: it kept the id `brain` and a stable `served_name` while the underlying weights swapped dense-27B → 35B-A3B MoE, and downstream agents never noticed. The spec formalizes that as the mechanism that lets scenes "update over time as models evolve" without breaking anyone. ### Why this also solves scene-sharing security A published scene contains **only ids and parameters — never shell commands.** The launch commands live in your *local, vetted* registry. So activating a downloaded scene can only ever start models your own registry already trusts. If a scene references an id you don't have, Lumbridge Compute asks you to add it to your registry, showing the launch command for review — an explicit opt-in, not silent remote code execution. Declarative-by-construction; there is no field in which a scene can smuggle a command. --- ## Scene manifest `scenes/studio.scene.yaml` ```yaml apiVersion: lumbridge/v1 kind: Scene metadata: name: studio version: 3 # bump on any change; a published scene is reproducible description: "Live voice assistant — ears, brain, mouth, and music." author: karti tags: [assistant, voice, always-on] models: # stable ids; the registry resolves each - ears # ASR - brain # MoE LLM - voice # TTS - music # ACE-Step budget_gb: 100 # optional; overrides the Governor's global budget activation: order: footprint-asc # small models first so the big load spike lands last wait_healthy: true # block until each model's health check passes ``` `scenes/darkroom.scene.yaml` ```yaml apiVersion: lumbridge/v1 kind: Scene metadata: name: darkroom version: 1 description: "Overnight image farm — drops the brain to make room for FLUX.2-dev." tags: [image, overnight, unattended] models: - ears - voice - music - image # FLUX.2-dev — only fits because `brain` is not in this scene activation: order: footprint-asc wait_healthy: true ``` ### Fields | Field | Required | Meaning | |---|---|---| | `apiVersion` | ✔ | `lumbridge/v1`. | | `kind` | ✔ | `Scene`. | | `metadata.name` | ✔ | Unique scene name; the CLI handle. | | `metadata.version` | ✔ | Integer, bumped on any change. Reproducibility. | | `metadata.description` | ✔ | One line, shown in `lumbridge-compute scene ls`. | | `metadata.tags` | – | For the (future) registry search. | | `models` | ✔ | Ordered list of model ids resolved via the registry. | | `budget_gb` | – | Per-scene budget override; defaults to the global Governor budget. | | `activation.order` | – | `footprint-asc` (default) \| `listed`. | | `activation.wait_healthy` | – | Default `true`. Block until health checks pass. | A scene **never** contains: weight paths, shell commands, or GPU flags. Those live in the registry. This is load-bearing for both stability and security. --- ## Model registry `registry/models.yaml` — local to each box, evolves freely. Ids are the stable contract; everything under `serve` can change. ```yaml apiVersion: lumbridge/v1 kind: Registry version: 1 models: brain: name: "Qwen3.6 35B-A3B MoE (NVFP4)" footprint_gb: 66 # worst-case unified memory once serving (weights + KV + encoder) channel: stable # stable | latest — how aggressively to track new weights health: "http://localhost:8001/v1/models" serve: kind: vllm port: 8001 weights: "~/models/Qwen3.6-35B-A3B-NVFP4-Fast" served_name: # stable aliases so downstream clients survive a weight swap - brain - "local-moe" - "unsloth/Qwen3.6-35B-A3B-NVFP4-Fast" args: max-model-len: 65536 kv-cache-dtype: fp8 gpu-memory-utilization: 0.55 enforce-eager: true moe-backend: flashinfer_b12x # Unsloth DGX Spark recipe; critical for speed limit-mm-per-prompt: '{"image": 0, "video": 0}' env: CUTE_DSL_ARCH: sm_121a image: name: "FLUX.2-dev (FP8)" footprint_gb: 32 channel: stable health: "http://localhost:8007/health" serve: kind: diffusers # not vllm — a separate runtime (ComfyUI/diffusers) port: 8007 weights: "~/models/FLUX.2-dev" args: { dtype: fp8 } # ears / voice / music elaborated the same way (ASR, Chatterbox, ACE-Step). ``` ### `channel`: how scenes track evolving weights - `stable` — pin the exact `weights` path. Reproducible; you update deliberately. - `latest` — the registry may resolve to a newer quant of the same model family (e.g. a fresh NVFP4 build) on activation. Bleeding edge; use for your own box, not for scenes you publish for others. The scene picks the *id*; the registry's `channel` decides how much the weights are allowed to drift underneath it. That's the whole "scenes evolve as models evolve" story, made explicit and controllable. --- ## Governor interaction On `activate`, Lumbridge Compute computes the diff between the running set and the target scene's `models`, then: 1. **Stops** running models not in the scene (frees their footprint first). 2. **Starts** the scene's models in `activation.order`, each passing **admission control** against `budget_gb` before launch. 3. Waits for health if `wait_healthy`. The watchdog runs throughout, unchanged — the safety net if any `footprint_gb` is wrong. A scene can never talk the Governor into over-committing; admission control is not bypassable by a scene.