This application is a local-first studio workstation. The primary jobs are:
- lighting control
- audio control
- Stream Deck / Companion control-surface support
- production planning as a secondary workspace
Everything assumes a single trusted machine with no cloud dependency. Supported hardware assumptions are documented in HARDWARE_PROFILE.md.
- owns native windowing, startup routing, recovery presentation, and operator-facing shell chrome
- supervises the Rust engine as a child process
- keeps shell view models thin and derived from engine snapshots
- owns persisted state, schema migrations, and legacy import
- owns planning, commissioning, dashboard, support, lighting, audio, and control-surface contracts
- owns device-facing safety rules, diagnostics, and recovery behavior
- exposes snapshots and commands over the native protocol in
native/protocol/v1.md
- lighting adapters stay behind engine-owned health, recall, and failure contracts
- audio adapters stay behind engine-owned sync, recall, and safety contracts
- control-surface exports and bridge behavior stay engine-owned
The Electron/Next.js runtime was removed in v2.1.0. A one-way import path in native/rust-engine/src/legacy_import.rs remains so that operators migrating from a pre-v2.0.0 installation can bring their old db.json forward on first native launch. The legacy runtime itself is no longer in the repository.
Any native studio domain should follow the same shape:
- keep persisted values explicit and serializable
- separate persisted configuration from transient connection or probe state
- keep storage ownership in the Rust engine
- expose a clear snapshot shape
- expose command handlers for every write path
- emit explicit change events when authoritative state mutates
- request snapshots through the engine controller
- render operator-visible state without owning business logic
- avoid recreating server-style fetch layers inside QML
- expose readiness, failure, and recovery state through engine snapshots
- keep hardware disconnect and recovery behavior visible to the operator
- keep device I/O policy in the engine, not in QML
- validate storage and command behavior at the engine boundary first
- add smoke or acceptance coverage for packaged startup, failure, and lifecycle behavior
native/rust-engine/src/planning.rs: planning storage, snapshots, and mutationsnative/rust-engine/src/commissioning.rs: commissioning state and probe flowsnative/rust-engine/src/lighting.rs: lighting snapshot, recall, and simulated backend boundarynative/rust-engine/src/audio.rs: audio snapshot, sync, recall, and simulated backend boundarynative/rust-engine/src/support.rs: backup, restore, and diagnostics support flowsnative/rust-engine/src/control_surface.rs: Stream Deck bridge and Companion export generationnative/qt-shell/qml/Main.qml: operator shell surface derived from engine state
When adding a feature, define or extend the engine contract first. Only then wire the shell and adapter layers. If a change would move product state or device policy into QML, it is probably going in the wrong direction.