# Architecture ## Design objectives Jukebox must provide a reliable voice-to-expert-prompt path while remaining safe for Omarchy's shared shell process. The visual console is important, but preservation of the user's speech and deterministic recovery from failures take priority over animation or convenience. ## Component boundaries ### Omarchy plugin UI `Jukebox.qml` is a keep-loaded `panel` entry point. It owns only presentation and low-risk orchestration: - observe the state contract; - display recording, transcription, upscaling, success, and error states; - render the live spectrum supplied by a disposable analyzer process; - persist bounded geometry, transformation mode, and model selection; - request start or finish through the controller; - expose `open()` and `close()` for Omarchy shell lifecycle testing. It does not capture raw audio, transcribe speech, store credentials, or invoke provider APIs directly. ### Session controller The controller owns the state machine and one-session lock: `idle → recording → finalizing → generating → review → delivering → idle` Every error returns to a recoverable state through a named failure result. The controller remembers the intended destination window before asynchronous work begins. It never injects text into a different window silently. Transformation creates a private review draft; insertion is a separate explicit action. When the panel loads, a lock-aware reconciliation action checks whether any persisted non-idle state still has the recording or review artifact that proves it is valid. A stale recording, finalization, or generation state left by an interrupted process returns to idle; an active Voxtype meeting or recoverable review draft is preserved. ### Transcription engine Voxtype provides local capture and transcription through Parakeet or Whisper. Guided setup recommends an engine from available hardware, supports automatic language detection, and exposes a disposable microphone test. Meeting mode writes bounded chunks to disk rather than retaining a multi-hour recording in memory. A complete export is compiled once after finalization. ### Transformation compiler The compiler sends the complete transcript to a private Unix-socket bridge that expires after ten idle minutes. Codex app-server and Claude Code stream-json events feed the review deck progressively; an incompatible Codex app-server falls back to safe ephemeral `codex exec`. The completed provider message is authoritative. The bridge retries only the selected provider/model and never silently downgrades or imposes a hidden quality budget. Transcript bytes are data only. They cannot affect provider routing or persistent configuration. Provider, model, mode, and delivery changes come only from explicit settings controls or the configuration CLI. A future voice-command channel would require a separate typed contract and confirmation before any private transcript is dispatched; the transformation payload itself is never interpreted as control input. Codex, Claude Code, and an initial OpenRouter adapter ship behind one provider contract in v0.2. Future adapters must sit behind this boundary rather than changing capture, transcription, review, or delivery. The open tracks are [Gemini CLI](https://github.com/JamesWeatherhead/jukebox/issues/2) and [OpenRouter hardening](https://github.com/JamesWeatherhead/jukebox/issues/3). CLI adapters delegate to the provider's documented status/invocation interface without reading its credential store; OpenRouter uses PKCE and keeps its user-controlled key in the Linux Secret Service keyring. Every adapter validates the selected model, rejects hidden downgrade, keeps transcript content outside process arguments, and returns the same typed success or bounded failure contract. The OpenRouter completion transport never follows redirects while carrying a bearer token. It enforces a hard response-byte limit before JSON parsing for both declared-length and streaming/unknown-length bodies. Provider status, HTTP, parsing, timeout, and size failures collapse to content-free error classes rather than surfacing credentials or remote response bodies. ### Delivery At recording start, the controller stores the exact originating Hyprland address and stable window metadata in private runtime state. After transformation, the user reviews and may edit the draft. Before Insert or Copy can run, the UI sends the edited prompt through the controller's bounded standard-input channel and waits for an atomic private write to succeed. Insert then copies that committed result to the clipboard, restores the exact window through Hyprland's Lua dispatcher, verifies focus, and invokes the terminal's native paste chord without pressing Enter. Native bracketed paste carries long output as one payload rather than thousands of fallible virtual keystrokes. If the edit cannot be saved, the origin no longer exists, or paste fails, the review draft remains recoverable and the controller never redirects text into another window. ## State and data locations Runtime state uses XDG locations and must not live in the plugin repository: - `$XDG_RUNTIME_DIR/voxtype/` — shared Voxtype meeting state plus private Jukebox locks, originating-window identity, and content-free delivery receipt; - `$XDG_STATE_HOME/jukebox/` — geometry, rollback journal, diagnostics, and seven-day generated-prompt history; - `$XDG_CONFIG_HOME/jukebox/` — transformation-mode selection, model selection, and user configuration; - `$XDG_DATA_HOME/voxtype/` — transcription models and meeting storage managed by Voxtype. All transcript and prompt files are mode `0600`. Raw drafts are deleted after successful delivery, failed drafts expire after 24 hours, and generated prompts expire after seven days by default. Repository fixtures must be synthetic. ## Omarchy lifecycle - The manifest declares only `panel` and `keepLoaded: true`. - Omarchy loads the plugin inside the existing `omarchy-shell` process. - The plugin must survive hot reload, explicit rescan, shell restart, disable/re-enable, and removal. - Disabling the plugin must not stop or mutate the Voxtype service unexpectedly. - No plugin code writes into `/usr/share/omarchy/`. - No second Quickshell process is started. ## Extension boundary Transformation providers attach at the compiler boundary; future destinations and capabilities attach after compilation through a typed routing interface. Neither extension path expands the recorder state machine. A visual capability rail is reserved for future modules, including the name **W1**, but W1 has no assumed contract or behavior in this release. ## Threat model Principal risks: 1. private speech or credentials entering Git history; 2. prompt injection inside a transcript overriding compiler policy; 3. focus changes causing delivery into the wrong application; 4. an unbounded child process destabilizing the shared shell; 5. shell reloads creating duplicate recorders or analyzers; 6. partial transcription or model failure losing the original speech; 7. dependencies or install commands receiving unnecessary privileges. 8. transcript content silently changing provider routing or persistent settings; 9. an asynchronous review edit racing the delivery action and sending stale text. The test plan contains explicit gates for each risk.