* feat(capabilities): add core-owned midi-input control-plane domain (#873, #880) The MIDI analog of audio-input: a core-owned provider-coordinator over MIDI device discovery, selection, and shared open/close sessions. Separate from audio-input (whose source/open contract is audio-frame-centric) and not owned by any feature plugin, so the device-access boundary outlives the input-setup wizard. `discover` is the Web-MIDI permission boundary; selection persists by redaction-safe logicalSourceKey; diagnostics redact device labels and never carry raw MIDI messages. - static/capabilities/midi-input.js + load-order wiring in both shells - spec 012 + capability-domains/safety-matrix entries; midi-control narrowed to mappings-only (split) - 9 domain tests against the real runtime Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(input_setup): bundled plugin owning input-calibration + Web-MIDI provider (#872) Bundled core plugin that supplies the Web-MIDI source provider to the core midi-input domain, owns the input-calibration workflow domain (run/status/ inspect), and renders the per-instrument wizard (guitar/bass -> audio-input + note_detect; keys/drums -> midi-input live note/pad test). Idempotent hydration; redaction-safe. .gitignore allowlists the in-tree plugin. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(onboarding): input-device setup step between paths and calibration (#874) After instrument-path selection and before the note-detect calibration challenge, dispatch input-calibration `run` (fire-and-launch) and await the `calibration-done` event. Fail-soft: a non-handled outcome (plugin/runtime absent) advances immediately so onboarding can never be stranded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(midi-input): ship a built-in Web-MIDI provider in the core domain Move the Web-MIDI source provider out of input_setup and into the core midi-input domain so every consumer (piano, drums, input_setup) gets MIDI devices from the domain without depending on any one plugin being loaded. input_setup is now a pure midi-input requester (manifest role updated). Prepares piano/drums full consumption (#876/#877). +1 domain test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(input_setup): Settings panel to re-run input setup (#878) Adds a settings.html with a "Set up input devices" button (window ._inputSetupRelaunch) that re-runs the wizard for the player's selected instrument paths (from /api/progression; falls back to all instruments). Makes the calibration wizard re-launchable outside first-run onboarding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(midi-control): formalize the midi-input/midi-control split (#882) Narrow the reserved midi-control domain to mappings ONLY (CC/pitchbend/note → action routing), consuming the delivered midi-input domain for device access. Adds spec 013 defining the contract + intended consumers (feedback-plugin-midi, drums learn-mode), updates the safety-matrix row, and cross-references it from capability-domains. Per governance, midi-control stays RESERVED (no runtime domain) until a concrete mapping consumer + tests exist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(onboarding): wait for input_setup before the calibration step (#874) The input-setup wizard is a mandatory onboarding step, but plugins load asynchronously — in the desktop app (40+ plugins) the user can reach path selection and click Next before input_setup has registered its input-calibration owner. The dispatch then got a no-owner outcome and onboarding fell through to the calibration challenge, silently skipping the wizard. Now wait (bounded, 8s) for the plugin's public global before dispatching; fall through only if it never appears. Race-verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(onboarding): add Song directory step after name+avatar (#874) New first-run step (now step 2 of 4: name+avatar → song directory → paths → calibration challenge) where the player sets their songs folder, fixing the "folder not configured" error on a fresh install. Saves to settings (dlc_dir) and kicks a library scan; persists to config.json so it survives restart. A native folder picker is offered on desktop (window.slopsmithDesktop .pickDirectory); web users type/paste the path. "Skip for now" leaves it unconfigured (settable later in Settings). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(input_setup): filter MIDI entries out of the guitar audio-input picker (#876) Other plugins export pseudonymized MIDI sources ('midi-input-N') into the audio-input domain; they aren't audio inputs and the cryptic labels confused the guitar/bass device dropdown. Filter them out so only real audio inputs show. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(input_setup): de-dupe audio input picker entries (#876) The desktop audio engine enumerates the same device under multiple driver types, so the guitar audio-input dropdown showed repeated entries. De-dupe by display label (paired with the desktop fix that surfaces real device names). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(midi-input): drop vanished devices on re-discovery; reset setup confirm on switch Codex preflight findings: - midi-input domain `_discover()` only upserted enumerated sources, so an unplugged device (statechange re-discovery) lingered in list-sources and later open/select hit stale state. Reconcile each provider's sources against the fresh enumeration (close any live session, keep the selectedKey preference). - input_setup MIDI panel left "Continue" enabled (and the instrument marked done) after switching the device selection following a prior hit. Reset the waiting state + disable Continue on every selection change, and discard a stale open if the selection changed mid-await. +1 reconciliation test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(midi-input): coalesce concurrent opens; commit shown audio source pre-calibration Codex re-review (round 2): - midi-input domain: two concurrent open-source calls for the same source both passed the `sessions.get` guard and each called provider.open(), which for the built-in Web-MIDI provider overwrites the shared input.onmidimessage handler and orphans the earlier session — leaving the device silent. Coalesce in-flight opens onto one provider session (await the pending open, adopt its session; re-check after open and release a redundant handle if another open won). +test. - input_setup: the guitar/bass audio <select> shows its first option by default but fires no `change`, so on a first run with nothing selected, audio-input was never told before launchCalibration(). Commit the shown option on render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(midi-input): longer timeout for MIDI permission commands; stale-open guard in wizard Codex re-review (round 3): - The advertised command surface ran `discover`/`open-source` through the 250 ms default handler timeout, but those front a real Web-MIDI permission prompt / device open that commonly takes longer, so dispatch returned `failed` while the operation was still completing. Add per-(capability,command) timeout overrides (15 s for those two), folding the existing audio-mix special-case into the same table so both the command() and dispatch() paths honor it. - input_setup MIDI panel: openSelected() compared the mutable shared `activeKey` after its awaits, so a device switch mid-open could bind the old device's listener / close the wrong session. Capture the requested key in a local and use a generation guard to discard a superseded open. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(onboarding): detect 200-with-error song-dir saves; close MIDI session on skip Codex re-review (round 4): - /api/settings reports an invalid folder as a 200 response with an `error` body (a bare dict return, not a non-2xx status), so saveSongDir's res.ok-only check treated the failure as success and advanced onboarding without saving. Parse the body and throw on `error` too. - input_setup: the opened MIDI test session was only closed on the Continue button, so using the generic "Skip for now" after scanning leaked the listener and kept the Web-MIDI input live. Run teardown on every panel exit via a per-panel cleanup hook invoked by advance(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(input_setup): don't hard-code Web MIDI in the device wizard Codex re-review (round 5): the MIDI panel gated availability on navigator.requestMIDIAccess and filtered sources to providerId === 'web-midi', which defeats the midi-input domain's provider-coordinator abstraction — a native/desktop MIDI adapter registered with the domain would be reported unavailable and hidden from the picker. Gate availability on the domain (window.slopsmith.midiInput) and show every source it surfaces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
24 KiB
Capability Roadmap
This roadmap keeps the first capability PR reviewable while making the future domain plan explicit. PR1 ships the substrate and only the domains whose current behavior is implemented, diagnosed, and tested. Future domains stay planned or reserved until the PR that implements their host workflow also adds runtime registration, compatibility shims when needed, diagnostics, and tests.
plugin-capability-inventory.md is the current plugin evidence pass for this roadmap. It inventories 41 included plugins, confirms that no included manifest currently declares capabilities, and maps legacy behavior to recommended future domains. Roadmap entries below should be read together with that inventory: domains listed here are planned names and migration targets, while the inventory explains which real plugins are likely to use or declare them.
PR1 Domain Set
PR1 should include these delivered domains:
| Domain | Scope | Owner Kind | Safety | Why It Is In PR1 |
|---|---|---|---|---|
pipeline |
Core diagnostic surface | diagnostic | diagnostic-only | Exposes capability graph inspection, validation, and participant enablement diagnostics. |
diagnostics |
Core diagnostic surface | diagnostic | diagnostic-only | Lets support bundles explain capability state safely. |
library |
Core app workflow | provider-coordinator | safe | Models current local and plugin-provided library sources, source selection, and song sync. |
The core/runtime domains in PR1 are intentionally small: diagnostics snapshots, pipeline graph operations, and one concrete app workflow (library). Runtime claim and override mechanics are covered by focused behavior tests, but no plugin-owned proving domain is promoted into the runtime graph in PR1.
diagnostics and pipeline are support domains, not feature workflow domains. diagnostics is the read-only snapshot/export facade consumed by support bundles and the Capability Inspector. pipeline is the graph operations facade: resolve, inspect, validate, and enable or disable participants.
PR1 Compatibility Shims
PR1 does not expose expected compatibility shims for library. Library is implemented as a native provider-coordinator domain; provider attribution comes from backend owner_plugin_id metadata and browser runtime provider participants.
Future domains should not add expected shim entries until their own implementation PR. A domain PR owns its compatibility story.
Audio Graph/Session And Effects Slices
The audio graph/session and effects slices promote these domains after PR1:
| Domain | Scope | Owner Kind | Safety | Compatibility Bridges |
|---|---|---|---|---|
audio-mix |
Song volume, fader participants, route summary, analyser bridge accounting | provider-coordinator | safe | audio-mix.fader-registry, audio-mix.song-volume, audio-mix.analyser |
audio-input |
Redaction-safe input source registration, selection, open-session lifecycle, channel compatibility, and provider migration diagnostics | provider-coordinator | sensitive | audio-input.legacy-source |
audio-monitoring |
Monitoring provider selection, explicit user-action start/stop, direct-monitor policy, requester sharing, and audio startup barrier readiness | provider-coordinator | sensitive | audio-monitoring.audio-barrier, audio-monitoring.legacy-provider |
stems |
Stem automation claims and active provider status | coordinator plus plugin provider | safe | stems.master-volume, stems.private-state |
audio-effects |
Provider-selected effect routes, constrained chain plans, route/stage controls, fallback, and native-executor bridge accounting | provider-coordinator | sensitive | audio-effects.legacy-tone-controls, audio-effects.legacy-nam-routing, audio-effects.legacy-midi-amp |
core.audio.session is the runtime coordinator for all four domains. It owns audio-mix, audio-input, and audio-monitoring; for stems, it coordinates the active Stems provider without replacing the Stems plugin as the owner of actual stem playback/state.
The focused audio-mix control-plane slice promotes fader discovery, read/write operations, committed-value events, native-over-legacy duplicate handling, route/analyser inspection, and compatibility removal gates into audio-mix. During migration, window.slopsmith.audio.registerFader(...) remains available as a compatibility adapter, but the player mixer consumes the audio-mix control plane as its source of truth.
The focused audio-input control-plane slice promotes source listing, prompt-free selection/inspection, explicit provider enumeration, open/close dispatch, channel-shape compatibility, selected-source persistence, shared requester sessions, and redaction-safe failure diagnostics into audio-input. During migration, legacy browser, desktop, or plugin-specific input handoffs should be recorded as audio-input.legacy-source bridge hits. Native providers own the visible source when they share a logical source key with a compatibility-backed source; the compatibility source remains diagnostics-only until normal playback shows no unexpected legacy hits.
The focused audio-monitoring control-plane slice promotes monitoring provider registration, selected-provider persistence, explicit user-action live monitoring start, shared requester attachment, final-requester stop, provider disappearance/orphan diagnostics, direct-monitor preference/control summaries, prompt-free status inspection, and redaction-safe failure outcomes into audio-monitoring. Fresh monitoring starts from plugins/background code return user-action-required; background requesters may attach only to an already-active compatible monitoring session. Native providers own a logical monitoring path when they share it with compatibility-backed startup barrier or legacy monitoring surfaces, and the legacy path remains diagnostics-only until normal playback shows no unexpected bridge hits.
The focused audio-effects control-plane slice promotes provider registration, user-authorized chain selection, constrained chain-plan resolution, route bypass/restore, segment activation, stage bypass/parameter routing, fallback accounting, and redaction-safe diagnostics into audio-effects. Providers propose opaque chain plans; trusted desktop/native code validates the references and physically loads NAM, IR, VST, or utility stages. During migration, legacy tone controls, NAM Tone/Rig Builder native-preset route interception, and MIDI/external effect handoffs should be recorded as audio-effects bridge hits. Bridge removal gates are: NAM Tone and Rig Builder register native providers, normal playback resolves through audio-effects without fetch interception, failure paths degrade to NAM Tone or bypass cleanly, repeated hydration does not duplicate providers/routes, and support snapshots contain no local paths, filenames, model/IR names, URLs, raw native preset JSON, VST state blobs, handles, callbacks, DOM nodes, audio buffers, samples, or waveforms.
Playback Control Plane Slice
The playback slice promotes playback from a deferred domain to an active exclusive-owner core domain. It owns transport commands (start, pause, resume, stop, seek, set-loop, clear-loop, inspect), lifecycle events (playback:requested, playback:loading, playback:ready, playback:started, playback:paused, playback:resumed, playback:seeking, playback:seeked, playback:ended, playback:stopped, route events, bridge hits, and loop events), and redaction-safe diagnostics for session, target, timing, route, loop, requester, observer, bridge, and recent outcome state.
The implementation deliberately keeps raw transport handles in static/app.js: the domain host registers a private adapter and receives sanitized snapshots instead of exposing the <audio> element, JUCE player, decoded audio buffers, waveform data, or native route handles. Playback targets expose a pseudonymous arrangement-scoped targetId plus a hashed per-song settingsKey so observers can store local per-song settings without reading raw filenames or paths. Compatibility bridges currently account for window.playSong, window.slopsmith transport helpers, legacy song events, loop helpers, media snapshots, route switching, and native-route handoff. Fresh audible starts require authorization: "user-action"; background requesters can inspect or control only an existing compatible session according to the command conflict policy.
Playback bridge removal gates are: bundled and first-party plugins use native playback dispatch for normal requester/observer workflows; normal play/pause/seek/loop/route smoke runs show no unexpected bridge hits beyond compatibility-only listeners; playback diagnostics distinguish denied, no-target, stale, cancelled, degraded, unavailable, failed, and stopped outcomes; repeated plugin hydration does not duplicate requesters, observers, wrappers, or bridge entries; and exported support snapshots contain no raw song filenames, paths, URLs, media handles, buffers, waveforms, samples, or recordings.
Progression Domain Slice
The progression slice (spec 010) promotes progression as an active exclusive-owner core domain: mastery rank (onboarding calibration + per-path levels), the data-driven challenge/quest engine under data/progression/, the Decibels wallet (frontend rename of the unified XP store; spend tracked separately from lifetime earnings), and the cosmetics shop. Commands are inspect, record-event (whitelisted types; minigame_run in v1), list-shop, buy-item, and equip-item (buy/equip require explicit user action). Lifecycle events mirror as progression:* window events.
Deferred follow-up slices: a contributor role so plugins ship their own challenge/quest content (drums challenges from a drums-scoring plugin, quest-pool entries from minigame plugins), and drums scoring wiring so song_completed {instrument: "drums"} goals become satisfiable.
Recommended Next Slices
The plugin inventory suggests this migration order after the audio graph/session and playback slices:
jobs: coordinate conversion, import, update, preview, and studio work with progress, cancellation, retry, and terminal failure semantics.note-detection(control-plane slice done — see spec-009): continue with chart-path/engine migration onto bindings; audio-input coupling and calibration diagnostics are follow-up slices.- UI contribution host: migrate navigation, plugin screens, player controls, player panels, overlays, shortcuts, and guided tours under placement/lifecycle policy.
- Backend and privileged capability cleanup: migrate routes, plugin lifecycle, media import/export, recording, external services, and subprocess-backed workflows with explicit user confirmation and diagnostics redaction.
UI/UX Migration Path
This is the recommended order for UI/UX capability work only. It excludes audio semantics, backend route execution, media jobs, and plugin install/update behavior except where those systems need a visible contribution point.
| Order | Slice | Domains | Legacy Surfaces To Bridge | Migration Target | Removal Gate |
|---|---|---|---|---|---|
| 1 | UI contribution substrate | ui.navigation, ui.plugin-screens, settings, ui.player-controls, ui.player-overlays, ui.player-panels |
Manifest nav, screen, settings, direct DOM insertion, screen-specific globals |
Shared contribution registry with regions, ordering, mount/unmount, visibility, focus, teardown, diagnostics, and compatibility shim accounting | Every legacy UI field is represented as a contribution in diagnostics, with no duplicate mounts after script rehydration. |
| 2 | App navigation and plugin screens | ui.navigation, ui.plugin-screens |
window.showScreen wrappers, plugin nav entries, ad hoc screen initialization |
Central screen host that owns navigation events, plugin screen lifecycle, current-screen state, and back/restore behavior | Plugins can register screens without wrapping showScreen; legacy wrappers are observed only as compatibility hits. |
| 3 | Settings contribution host | settings |
Manifest settings.html, plugin settings panels, settings backup hints |
Settings registry with panel metadata, redaction class, backup/import allowlist summary, visibility policy, and diagnostics | Settings UI can render from registered contributions; settings values remain plugin-owned and redacted. |
| 4 | Keyboard and command UX | keyboard-shortcuts plus UI host regions |
window.registerShortcut, panel-scoped shortcut helpers, help panel entries |
Shortcut contribution registry with scope, priority, conflict reporting, enable/disable state, and help metadata | Shortcut conflicts are diagnosable and panel-scoped shortcuts do not require private registries. |
| 5 | Player controls | ui.player-controls |
Direct player control DOM edits, control popovers, button/slider globals | Ordered player-control regions with stable command buttons, popovers, sliders, disabled states, and contribution teardown | Player controls can be added/removed/reordered without plugins mutating the control bar directly. |
| 6 | Player overlays | ui.player-overlays, tours |
Overlay canvases, tour overlays, highway visibility listeners, direct z-index management | Overlay host with anchors, z-order, hit-testing, renderer compatibility flags, visibility events, and cleanup | Fretboard, section map, tours, transpose, step mode, and similar overlays can coexist without private layering rules. |
| 7 | Player panels | ui.player-panels |
Splitscreen panel DOM, panel-local highway instances, panel-local shortcuts | Panel host with layout slots, active-panel focus, per-panel renderer selection, per-panel shortcuts, visibility, and teardown | Splitscreen-style panels can be composed through host APIs instead of wrapping playback/screen globals. |
| 8 | Visualization UX | visualization |
type: "visualization", window.slopsmithViz_*, viz picker state, auto-match hooks |
Renderer provider registry with picker integration, auto-match ordering, context-type metadata, fallback/revert events, and per-panel selection | Renderer selection and failure recovery are fully attributed in diagnostics; picker options no longer depend on global scans. |
| 9 | Library and guided UX extensions | ui.library-card-injection, tours |
Library card buttons, tour registration globals, target selectors | Contribution APIs for library card actions and guided-tour steps with applicability, target resolution, and action-result events | Library actions and tours can be inspected, disabled, and tested independently of plugin-private DOM injection. |
| 10 | Theme and polish surfaces | settings or candidate ui.theme |
Global theme settings, direct stylesheet/class mutation | Theme contribution metadata for tokens, selected theme, preview/apply/restore lifecycle, and diagnostics without user secrets | Themes are reversible and attributable, and visual changes do not depend on hidden global state. |
The UI contribution substrate should land first because every later UI/UX slice needs the same basic primitives: contribution identity, stable regions, deterministic ordering, mount/unmount, visibility, focus, teardown, diagnostics, and compatibility shim hit accounting. Specialized UI domains should stay small and should only add behavior that the shared substrate cannot express cleanly.
UI/UX migration should preserve current plugin fields during the transition. Core can translate manifest nav, screen, and settings into contribution records before plugin scripts hydrate, then let runtime plugins re-register richer metadata when their scripts load. The removal gate for each legacy UI API is not just a new command name; it is proof that repeated script hydration, screen switching, player navigation, and plugin disable/enable cycles do not duplicate DOM nodes, wrappers, listeners, shortcuts, canvases, or tours.
Deferred Domains
These domains are planned but should stay out of the runtime graph until a host workflow exists:
| Domain | Expected Ownership | Expected Safety | Candidate Scope | Implementation Trigger |
|---|---|---|---|---|
stems |
coordinated plugin provider | safe | Stem mute/restore, ownership claims, manual override events, and requester/observer coordination. | Promoted by the audio graph/session slice as a coordinated provider domain. |
ui.navigation |
exclusive-owner | safe | Navigation contributions and screen-change events. | A UI host PR that owns contribution placement and route/screen semantics. |
ui.plugin-screens |
exclusive-owner | safe | Plugin screen registration and lifecycle. | A screen host PR with mount/unmount and visibility policy. |
settings |
exclusive-owner | sensitive | Plugin settings contribution metadata without settings values. | A settings contribution PR with redaction rules and migration story. |
audio-mix |
multi-provider | safe | Mixer fader registration and current fader inspection. | Promoted by the audio graph/session slice. |
audio-monitoring |
multi-provider | sensitive | Monitoring provider selection, live start/stop lifecycle, shared requester sessions, direct-monitor state, and redacted failure diagnostics. | Promoted by the audio graph/session slice and implemented by the audio-monitoring control-plane slice. |
backend.routes |
multi-provider | privileged | Server route/provider participation and route inspection. | A backend domain PR with concrete core/provider workflow, privilege review, and route diagnostics. |
ui.player-controls |
exclusive-owner | safe | Player-control contributions and ordering. | A first-party player-control host and layout policy. |
ui.player-panels |
exclusive-owner | safe | Player panel contributions, mount/unmount, visibility, ordering. | A panel host with layout and focus rules. |
ui.player-overlays |
exclusive-owner | safe | Overlay contributions layered over player or highway surfaces. | Overlay placement and z-order rules that coexist with legacy overlays. |
plugins |
exclusive-owner | privileged | Plugin enable/disable/install/update workflows. | Visible user confirmation, rollback, and disabled-handler enforcement. |
jobs |
multi-provider | privileged | Long-running jobs, cancellation, status, failures. | Scheduling limits, cancellation semantics, and user-visible failures. |
midi-control |
multi-provider | sensitive | MIDI control mappings only (CC/pitchbend/note → action routing), consuming midi-input for device access. Device discovery/selection/open is split out to the delivered midi-input domain (spec 012). |
A concrete mapping/routing workflow on top of the midi-input device plane (#882). |
audio-input |
multi-provider | sensitive | Audio input device providers, source selection, open/close lifecycle, shared sessions, and redacted failure diagnostics. | Promoted by the audio graph/session slice and implemented by the audio-input control-plane slice. |
tempo-clock |
multi-provider | safe | Tempo/clock provider registration and consumers. | A concrete tempo source and consumer workflow. |
Deferred domains may remain documented or reserved, but they should not produce expected shims, inspector links, or runtime handlers before their implementation slice.
Candidate Domains From Plugin Inventory
These candidate domains were surfaced by the included plugin inventory but are not yet part of the core deferred-domain table. They should be promoted only if a focused spec proves that the boundary is clearer than folding the behavior into an existing domain.
| Candidate Domain | Expected Ownership | Expected Safety | Candidate Scope | Initial Evidence |
|---|---|---|---|---|
ui.library-card-injection |
exclusive-owner | safe | Library card actions, placement, applicability, enabled/disabled state, and action-result events. | Find More and Sloppak Converter add library-card actions that are separate from browsable library providers. |
tours |
exclusive-owner | safe | Guided tour registration, eligibility, target resolution, step lifecycle, and screen/navigation dependencies. | Library/settings tours, tutorials, and guided plugin walkthroughs use tour-specific lifecycle behavior. |
keyboard-shortcuts |
exclusive-owner | safe | Shortcut contribution registration, scope, conflict resolution, enable/disable state, and help-panel metadata. | Splitscreen, Step Mode, and practice-style plugins use or imply scoped shortcuts beyond normal UI placement. |
media-import-export |
multi-provider | privileged | Upload/import/export/conversion requests, accepted file types, generated artifacts, cleanup, and failure semantics. | Editor, Tab Import, Profile Import, Sloppak Converter, Studio, and Rig Builder all move user files through backend workflows. |
recording |
multi-provider | sensitive | Arm/start/stop capture, take upload/import, capture-source binding, latency metadata, and storage cleanup. | Studio and karaoke workflows need capture/session semantics distinct from raw audio input. |
practice-session |
multi-provider | safe | Practice session lifecycle, goals, score/progress events, chart segment focus, and journal persistence boundaries. | Practice Journal, Minigames, Guitar Theory, Flappy Bend, and Note Detect imply practice/progression state. |
collaboration |
multi-provider | sensitive | Room/session lifecycle, participant identity redaction, shared playback sync, conflict policy, and disconnect recovery. | Multiplayer is a distinct real-time coordination surface. |
external-services |
diagnostic or privileged metadata | privileged | Network/download/subprocess integration inventory, endpoint attribution, confirmation policy, and failure diagnostics. | Update Manager, Find More, Sloppak Converter, and media jobs reach outside local Slopsmith state. |
Candidate domains can also remain as safety metadata on existing domains. For example, external-services may be more useful as a cross-cutting review tag than as a dispatchable runtime capability.
Domain Versioning
PR1 does not add per-domain versioning. The capability-pipelines.v1 standard versions the overall manifest/runtime/diagnostics contract. Domain evolution follows compatibility rules:
- Adding optional commands, events, diagnostics fields, or participant metadata is non-breaking.
- Removing or renaming commands/events is breaking.
- Changing ownership semantics is breaking.
- Changing command payloads, return payloads, or dispatch outcomes incompatibly is breaking.
- A breaking change requires either a future
capability-pipelinesversion or a clearly new domain name if parallel support is needed.
Per-domain versions should wait until Slopsmith has a concrete need for multiple incompatible versions of the same domain to coexist.
Future Domain PR Checklist
A PR that promotes a deferred domain into the runtime graph should include:
- User value and included/excluded command scope.
- Host workflow or provider implementation.
- Runtime domain review metadata.
- Manifest and runtime registration path.
- Compatibility shims only for legacy behavior the PR actually bridges.
- Diagnostics fields and redaction rules.
- Inspector behavior and meaningful labels/tooltips.
- Tests for valid metadata, invalid metadata, unsupported versions, disabled participants, command outcomes, and shim hit accounting.
- Documentation updates in the safety matrix and capability docs.
Before opening the PR, run the reusable review checklist in capability-review-preflight.md. It records the cross-cutting findings from previous capability reviews so each new slice can focus additional review research on the most recently merged PR.