mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-11 03:09:57 +00:00
rename: slopsmith → feedBack, byron → got-feedBack (#537)
* Update GitHub repo references from feedback* to feedBack* * rename: slopsmith -> feedBack, byron -> got-feedBack Renames across the entire codebase: - slopsmith/Slopsmith/SLOPSMITH/SlopSmith -> feedBack/FeedBack/FEEDBACK/FeedBack - byron/Byron/Byrongamatos -> got-feedBack/got-feedBack/got-feedBack - /home/byron/ -> /opt/got-feedBack/ - byron@ougsoft.com -> hi@got-feedBack.org - github.com/byrongamatos/ -> github.com/got-feedback/ - com.byron. -> com.got-feedback. - SLOPSMITH_ env vars -> FEEDBACK_ with backward-compat fallback - Protocol/storage strings migrated with read-old/write-new pattern - window.slopsmith JS API -> window.feedBack (canonical) + backward-compat alias Refs: #rename-slopsmith * rename: complete regen against current main + fix backward-compat alias Regenerated the slopsmith->feedBack / byron->got-feedBack rename on top of current main (3 commits had landed since the branch: #572/#554/#574), resolving the four content conflicts in favour of main's newer content (autoplay/auto-exit, accuracy-badge, Virtuoso re-home, feedpak badge). Completion fixes on top of the mechanical rename: - Re-apply rename to post-branch content the original rename never saw: window.slopsmith(.Tour) consumers in lessons.js / notifications.js / onboarding-tour.js, and the matching JS + python tests (autoplay_exit, progression_*, test_feedpak_extension FEEDBACK_* env vars). The test env vars now match server.py (which reads FEEDBACK_SYNC_STARTUP / FEEDBACK_SKIP_STARTUP_TASKS), so the sync-startup test exercises the real path again. - Restore the window.slopsmith backward-compat alias dropped during conflict resolution, and move the bus aliases to AFTER the _feedBackExisting merge block so they reference the fully-assembled object (also fixes the loop_api.test.js API-surface regex, which the original PR latently broke). - Drop the stray empty data/web_library.db (runtime DB lives in CONFIG_DIR) and gitignore it. - Fix stale tone-source test: feed[dB]ack -> fee[dB]ack to match shipped source labels. Verified locally (org CI billing-blocked): JS 819/819 pass; pytest 1669 passed / 1683 collected with 0 import errors; zero residual slopsmith/byron except the two intentional window.slopsmith aliases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * rename: implement advertised backward-compat + prune dead community plugins Address gaps where PR #537's "Backward compatibility" section was advertised but not implemented, and clean up the community plugin list. Env vars (FEEDBACK_* canonical, legacy SLOPSMITH_* honoured): - New lib/env_compat.py (getenv_compat / env_flag_compat) + tests. server.py (_env_flag + all FEEDBACK_* reads), diagnostics_hardware, gp2midi and tailwind_rebuild now resolve the legacy alias, so existing SLOPSMITH_UI / SLOPSMITH_PLUGINS_DIR / etc. deployments keep working. - Fix the rename collapsing plugins/__init__.py and minigames/routes.py from `FEEDBACK_PLUGINS_DIR or SLOPSMITH_PLUGINS_DIR` into a redundant `FEEDBACK_ or FEEDBACK_` (the fallback was silently lost). Storage (app.js update-channel): - Read feedBack-update-channel, fall back to legacy slopsmith-update-channel, and clear the legacy key on write — so a user's update-channel preference survives the rename instead of resetting to "stable". Community plugin list (README): the rename rewrote third-party repo URLs we don't own. Probed every one; their owners never renamed, so: - Restore the 13 live community plugins to their real slopsmith-* names. - Prune 6 that are 404 to the public (topkoa splitscreen/stems, OmikronApex tuner, Jafz2001 nam-rig-builder, DeathlySin song-preview, Erikcb91 shuffle). - Fix a pre-existing Guitar Theory clone-command typo (nam-tone -> guitar-theory). Verified: env_compat 7/7, JS 819/819, pytest 1690 collected / 0 import errors, rename-sensitive + startup suites green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: byrongamatos <xasiklas@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
byrongamatos
parent
a8ad02739a
commit
af2949677a
@@ -9,10 +9,10 @@ Depends on: `docs/NOTE_FAILURE_SPEC.md` (read that first)
|
||||
**Goal:** Working note detection plugin streaming detected notes via WebSocket.
|
||||
|
||||
This phase was previously tracked in a separate NOTE_DETECTION_PLUGIN_PLAN
|
||||
document (in the `slopsmith-plugin-notedetect` repository). The relevant scope
|
||||
document (in the `feedBack-plugin-notedetect` repository). The relevant scope
|
||||
is summarized here to avoid relying on an internal git-only reference:
|
||||
|
||||
- [ ] Plugin skeleton: `slopsmith-plugin-notedetect/` with plugin.json, routes.py, screen.js
|
||||
- [ ] Plugin skeleton: `feedBack-plugin-notedetect/` with plugin.json, routes.py, screen.js
|
||||
- [ ] Port TonalRecall YIN detection (aubio + sounddevice) to routes.py
|
||||
- [ ] WebSocket at `/api/plugins/note_detect/stream` streaming `{ note, freq, confidence, time }`
|
||||
- [ ] Device selection UI in screen.html
|
||||
@@ -138,7 +138,7 @@ shows the correct diagnostic labels.
|
||||
```
|
||||
Displayed for 1.5s, then fades.
|
||||
- [ ] Track `bestIteration` across all iterations for "Best" display
|
||||
- [ ] Emit `loop:complete` event via `window.slopsmith.emit()` so other plugins
|
||||
- [ ] Emit `loop:complete` event via `window.feedBack.emit()` so other plugins
|
||||
(practice journal) can record the data
|
||||
- [ ] Reset loop history when loop boundaries change or loop is cleared
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ late, wrong pitch, or not played at all.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This feature depends on the **note detection plugin** (`slopsmith-plugin-notedetect`),
|
||||
This feature depends on the **note detection plugin** (`feedBack-plugin-notedetect`),
|
||||
which provides real-time pitch detection via server-side aubio/YIN over WebSocket.
|
||||
The detection plugin streams `DetectedNote` events; this spec describes the
|
||||
**matching, judgment, and rendering** layer that consumes those events.
|
||||
@@ -55,10 +55,10 @@ Guitar → USB Adapter → sounddevice (server)
|
||||
Wire format: `{ note: "A2", freq: 110.0, confidence: 0.92, time: 1.234 }`
|
||||
|
||||
> **Plugin naming note:** The detection plugin's repository is named
|
||||
> `slopsmith-plugin-notedetect`, but the plugin registers with the id
|
||||
> `feedBack-plugin-notedetect`, but the plugin registers with the id
|
||||
> `note_detect` (snake_case). Its HTTP/WebSocket routes therefore appear
|
||||
> under `/api/plugins/note_detect/…`. There is no `window.slopsmithPlugin_*`
|
||||
> global pattern in Slopsmith — to check whether the detection plugin is
|
||||
> under `/api/plugins/note_detect/…`. There is no `window.feedBackPlugin_*`
|
||||
> global pattern in FeedBack — to check whether the detection plugin is
|
||||
> available at runtime, attempt a fetch to `/api/plugins/note_detect/status`
|
||||
> (or similar) or consult the `/api/plugins` list. Use the repo name only
|
||||
> in documentation links.
|
||||
@@ -335,7 +335,7 @@ The tracker must handle A-B looping:
|
||||
| `loopA`, `loopB` | Current A-B loop boundaries |
|
||||
| `audio.currentTime` | Actual audio playback position |
|
||||
|
||||
### New Events Emitted (via `window.slopsmith.emit`)
|
||||
### New Events Emitted (via `window.feedBack.emit`)
|
||||
|
||||
| Event | Payload |
|
||||
|------------------------------|------------------------------------------|
|
||||
@@ -373,7 +373,7 @@ There are three distinct threshold tiers — keep them conceptually separate:
|
||||
| `hitGlowDuration` | 0.5 | Green glow fade time (sec) |
|
||||
|
||||
Persist these settings in plugin-local storage (e.g. `localStorage` prefixed
|
||||
with the plugin id). Do **not** assume they can be saved through Slopsmith's
|
||||
with the plugin id). Do **not** assume they can be saved through FeedBack's
|
||||
`/api/settings` endpoint under a `notedetect_feedback` key — the current server
|
||||
only persists a fixed set of known settings keys. If backend support for a
|
||||
dedicated persisted key is added later, this plugin may migrate to `/api/settings`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Slopsmith Note Detect Bass Benchmark — v1
|
||||
# FeedBack Note Detect Bass Benchmark — v1
|
||||
|
||||
A bass-focused companion to the guitar benchmarks
|
||||
(note_detect_v1 + note_detect_v2). Tests `note_detect` against bass-
|
||||
|
||||
@@ -20,11 +20,11 @@ the guitar one:
|
||||
than guitar E2 at ~82 Hz. The benchmark should exercise that
|
||||
regime explicitly so we can spot regressions there.
|
||||
|
||||
How to run inside the slopsmith container:
|
||||
How to run inside the feedBack container:
|
||||
|
||||
docker cp docs/benchmarks/note_detect_bass_v1/build_benchmark.py \\
|
||||
slopsmith-web-1:/tmp/build_benchmark_bass.py
|
||||
docker exec slopsmith-web-1 python /tmp/build_benchmark_bass.py \\
|
||||
feedBack-web-1:/tmp/build_benchmark_bass.py
|
||||
docker exec feedBack-web-1 python /tmp/build_benchmark_bass.py \\
|
||||
/app/static/sloppak_cache/note_detect_benchmark_bass_v1.sloppak
|
||||
|
||||
After regenerating, copy the zip output to the tracked path with the
|
||||
@@ -351,7 +351,7 @@ def build(out_dir: Path):
|
||||
|
||||
arrangement = {
|
||||
'name': 'Bass',
|
||||
# Pad to 6 slots even on bass — slopsmith's `tuning_name()` only
|
||||
# Pad to 6 slots even on bass — feedBack's `tuning_name()` only
|
||||
# recognises named tunings (E Standard, Drop D, etc.) on 6-element
|
||||
# arrays, so a 4-element array shows up in the library card as the
|
||||
# raw numeric form ("0 0 0 0") instead of "E Standard". The
|
||||
@@ -371,7 +371,7 @@ def build(out_dir: Path):
|
||||
|
||||
manifest = {
|
||||
'title': 'Note Detect Bass Benchmark v1',
|
||||
'artist': 'Slopsmith',
|
||||
'artist': 'FeedBack',
|
||||
'album': 'Note Detection Benchmark',
|
||||
'year': 2026,
|
||||
'duration': round(end_t, 3),
|
||||
@@ -389,7 +389,7 @@ def build(out_dir: Path):
|
||||
{'id': 'full', 'file': 'stems/full.ogg', 'default': True},
|
||||
],
|
||||
'benchmark': {
|
||||
'id': 'slopsmith-note-detect-benchmark-bass',
|
||||
'id': 'feedBack-note-detect-benchmark-bass',
|
||||
'version': 1,
|
||||
},
|
||||
}
|
||||
@@ -461,7 +461,7 @@ def _build_zip(src_dir: Path):
|
||||
|
||||
|
||||
def _benchmark_readme(duration_s):
|
||||
return f"""# Slopsmith Note Detect Bass Benchmark — v1
|
||||
return f"""# FeedBack Note Detect Bass Benchmark — v1
|
||||
|
||||
A bass-focused companion to the guitar benchmarks
|
||||
(note_detect_v1 + note_detect_v2). Tests `note_detect` against bass-
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Slopsmith Note Detect Benchmark — v1
|
||||
# FeedBack Note Detect Benchmark — v1
|
||||
|
||||
A short test piece for tuning Slopsmith's `note_detect` plugin. Eight
|
||||
A short test piece for tuning FeedBack's `note_detect` plugin. Eight
|
||||
exercises, each isolating a specific detection failure mode. Run with
|
||||
**Detect** enabled, play through, then export the diagnostic JSON
|
||||
(Settings → Plugins → Note Detection → Download Diagnostic JSON, or
|
||||
@@ -43,4 +43,4 @@ Share the JSON (schema `note_detect.diagnostic.v1`). It includes:
|
||||
## Source
|
||||
|
||||
Built by `docs/benchmarks/note_detect_v1/build_benchmark.py` in the
|
||||
slopsmith repo. Tweak the exercise list there and regenerate.
|
||||
feedBack repo. Tweak the exercise list there and regenerate.
|
||||
|
||||
@@ -5,12 +5,12 @@ short exercises designed to isolate specific failure modes (open-string
|
||||
mono, fretted positions, octaves, sustained held notes, hammer-on /
|
||||
pull-off, sparse power chords, dense open chords, bends).
|
||||
|
||||
How to run inside the slopsmith container (recommended — has ffmpeg +
|
||||
How to run inside the feedBack container (recommended — has ffmpeg +
|
||||
pyyaml already):
|
||||
|
||||
docker cp docs/benchmarks/note_detect_v1/build_benchmark.py \
|
||||
slopsmith-web-1:/tmp/build_benchmark.py
|
||||
docker exec slopsmith-web-1 python /tmp/build_benchmark.py \
|
||||
feedBack-web-1:/tmp/build_benchmark.py
|
||||
docker exec feedBack-web-1 python /tmp/build_benchmark.py \
|
||||
/app/static/sloppak_cache/note_detect_benchmark_v1.sloppak
|
||||
|
||||
The output sloppak lands under `static/sloppak_cache/` on the host
|
||||
@@ -26,7 +26,7 @@ import sys
|
||||
import wave
|
||||
from pathlib import Path
|
||||
|
||||
import yaml # bundled with the slopsmith image
|
||||
import yaml # bundled with the feedBack image
|
||||
|
||||
# ── Benchmark parameters ────────────────────────────────────────────────
|
||||
BPM = 90.0
|
||||
@@ -411,7 +411,7 @@ def build(out_dir: Path):
|
||||
|
||||
manifest = {
|
||||
'title': 'Note Detect Benchmark v1',
|
||||
'artist': 'Slopsmith',
|
||||
'artist': 'FeedBack',
|
||||
'album': 'Note Detection Benchmark',
|
||||
'year': 2026,
|
||||
'duration': round(end_t, 3),
|
||||
@@ -430,7 +430,7 @@ def build(out_dir: Path):
|
||||
# Non-standard key — picked up by future tooling that wants to
|
||||
# detect "this is the benchmark, schema v1". The loader ignores it.
|
||||
'benchmark': {
|
||||
'id': 'slopsmith-note-detect-benchmark',
|
||||
'id': 'feedBack-note-detect-benchmark',
|
||||
'version': 1,
|
||||
},
|
||||
}
|
||||
@@ -545,9 +545,9 @@ def _build_zip(src_dir: Path):
|
||||
|
||||
|
||||
def _benchmark_readme(duration_s):
|
||||
return f"""# Slopsmith Note Detect Benchmark — v1
|
||||
return f"""# FeedBack Note Detect Benchmark — v1
|
||||
|
||||
A short test piece for tuning Slopsmith's `note_detect` plugin. Eight
|
||||
A short test piece for tuning FeedBack's `note_detect` plugin. Eight
|
||||
exercises, each isolating a specific detection failure mode. Run with
|
||||
**Detect** enabled, play through, then export the diagnostic JSON
|
||||
(Settings → Plugins → Note Detection → Download Diagnostic JSON, or
|
||||
@@ -590,7 +590,7 @@ Share the JSON (schema `note_detect.diagnostic.v1`). It includes:
|
||||
## Source
|
||||
|
||||
Built by `docs/benchmarks/note_detect_v1/build_benchmark.py` in the
|
||||
slopsmith repo. Tweak the exercise list there and regenerate.
|
||||
feedBack repo. Tweak the exercise list there and regenerate.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Slopsmith Note Detect Benchmark — v2
|
||||
# FeedBack Note Detect Benchmark — v2
|
||||
|
||||
A slower-paced companion to v1, focused on what players can actually
|
||||
land cleanly. Half-note spacing throughout (~1.33 s between events at
|
||||
|
||||
@@ -16,11 +16,11 @@ Goals vs v1:
|
||||
technique handling is the next algorithm focus, separate from
|
||||
measuring "do basic single notes + chords score correctly?"
|
||||
|
||||
How to run inside the slopsmith container:
|
||||
How to run inside the feedBack container:
|
||||
|
||||
docker cp docs/benchmarks/note_detect_v2/build_benchmark.py \\
|
||||
slopsmith-web-1:/tmp/build_benchmark_v2.py
|
||||
docker exec slopsmith-web-1 python /tmp/build_benchmark_v2.py \\
|
||||
feedBack-web-1:/tmp/build_benchmark_v2.py
|
||||
docker exec feedBack-web-1 python /tmp/build_benchmark_v2.py \\
|
||||
/app/static/sloppak_cache/note_detect_benchmark_v2.sloppak
|
||||
|
||||
After regenerating, copy the zip output to the tracked path with the
|
||||
@@ -375,7 +375,7 @@ def build(out_dir: Path):
|
||||
|
||||
manifest = {
|
||||
'title': 'Note Detect Benchmark v2',
|
||||
'artist': 'Slopsmith',
|
||||
'artist': 'FeedBack',
|
||||
'album': 'Note Detection Benchmark',
|
||||
'year': 2026,
|
||||
'duration': round(end_t, 3),
|
||||
@@ -392,7 +392,7 @@ def build(out_dir: Path):
|
||||
{'id': 'full', 'file': 'stems/full.ogg', 'default': True},
|
||||
],
|
||||
'benchmark': {
|
||||
'id': 'slopsmith-note-detect-benchmark',
|
||||
'id': 'feedBack-note-detect-benchmark',
|
||||
'version': 2,
|
||||
},
|
||||
}
|
||||
@@ -466,7 +466,7 @@ def _build_zip(src_dir: Path):
|
||||
|
||||
|
||||
def _benchmark_readme(duration_s):
|
||||
return f"""# Slopsmith Note Detect Benchmark — v2
|
||||
return f"""# FeedBack Note Detect Benchmark — v2
|
||||
|
||||
A slower-paced companion to v1, focused on what players can actually
|
||||
land cleanly. Half-note spacing throughout (~1.33 s between events at
|
||||
|
||||
+24
-24
@@ -1,6 +1,6 @@
|
||||
# Capability Domains
|
||||
|
||||
Capability domains are Slopsmith-wide coordination surfaces for core, bundled first-party plugins, external plugins, and future adapters. Plugins declare the runtime surfaces they use in `plugin.json`; core declares and owns host workflows directly in the runtime. These declarations let diagnostics and support tools reason about behavior without relying on private globals.
|
||||
Capability domains are FeedBack-wide coordination surfaces for core, bundled first-party plugins, external plugins, and future adapters. Plugins declare the runtime surfaces they use in `plugin.json`; core declares and owns host workflows directly in the runtime. These declarations let diagnostics and support tools reason about behavior without relying on private globals.
|
||||
|
||||
## Standards
|
||||
|
||||
@@ -63,21 +63,21 @@ Route-only external plugins that participate in library workflows without regist
|
||||
}
|
||||
```
|
||||
|
||||
The frontend exposes the current source list through `window.slopsmith.capabilities.command('library', 'list-providers')`. Public owner commands (`list-providers`, `refresh-providers`, `get-current`, `select-provider`, `sync-song`, `inspect`) are distinct from provider operations (`query-page`, `query-artists`, `query-stats`, `tuning-names`, `get-art`, `sync-song`). The app-owned handler delegates to the existing provider registry and source selector, so plugins should not scrape the `#lib-provider` dropdown.
|
||||
The frontend exposes the current source list through `window.feedBack.capabilities.command('library', 'list-providers')`. Public owner commands (`list-providers`, `refresh-providers`, `get-current`, `select-provider`, `sync-song`, `inspect`) are distinct from provider operations (`query-page`, `query-artists`, `query-stats`, `tuning-names`, `get-art`, `sync-song`). The app-owned handler delegates to the existing provider registry and source selector, so plugins should not scrape the `#lib-provider` dropdown.
|
||||
|
||||
Capability declarations may include a short `description`. The bundled Capability Inspector shows that text on expanded domain owner cards; when it is omitted, the inspector falls back to a compact generated owner summary.
|
||||
|
||||
## Audio Graph/Session Domains
|
||||
|
||||
The audio graph/session slice promotes four player-audio domains into the runtime graph: `audio-mix`, `audio-input`, `audio-monitoring`, and `stems`. The browser module at [static/capabilities/audio-session.js](../static/capabilities/audio-session.js) owns the active session boundary, contributes diagnostics under `slopsmith.audio_session.diagnostics.v1`, and records compatibility bridge hits for legacy audio surfaces.
|
||||
The audio graph/session slice promotes four player-audio domains into the runtime graph: `audio-mix`, `audio-input`, `audio-monitoring`, and `stems`. The browser module at [static/capabilities/audio-session.js](../static/capabilities/audio-session.js) owns the active session boundary, contributes diagnostics under `feedBack.audio_session.diagnostics.v1`, and records compatibility bridge hits for legacy audio surfaces.
|
||||
|
||||
`audio-mix`, `audio-input`, and `audio-monitoring` are core-owned provider-coordinator domains. They expose bounded inspect/register/start/stop style commands, redaction-safe diagnostics, and bridge accounting for legacy fader, analyser, input, and monitoring handshakes.
|
||||
|
||||
For `audio-mix`, native fader providers register mix participants with stable `participantId`, `kind`, `sourceMode`, optional `logicalFaderKey`, and `fader` metadata. The public command surface is `inspect`, `list-faders`, `get-fader-value`, `set-fader-value`, `inspect-route`, `inspect-analyser`, `register-participant`, and `unregister-participant`; provider operations are `fader.get-value`, `fader.set-value`, `route.get-current`, and `analyser.get-summary`. Providers own persistence for plugin faders and must return committed values from set operations so the player mixer can display the value that actually applied.
|
||||
|
||||
Legacy `window.slopsmith.audio.registerFader(...)` remains supported as an audio-mix compatibility bridge. The bridge registers a compatibility-backed participant, wraps legacy `getValue`/`setValue` callbacks as provider operations, and preserves `window.slopsmith.audio.getFaders()` for external callers. If a native participant and a legacy fader share the same logical fader key, the native participant owns the visible control; the legacy participant is retained for diagnostics with `supersededBy` and an `overshadowed` bridge hit. Removal gates for the bridge are: native providers cover bundled mixer integrations, diagnostics show no unexpected legacy hits in normal playback, and repeated plugin hydration does not create duplicate faders.
|
||||
Legacy `window.feedBack.audio.registerFader(...)` remains supported as an audio-mix compatibility bridge. The bridge registers a compatibility-backed participant, wraps legacy `getValue`/`setValue` callbacks as provider operations, and preserves `window.feedBack.audio.getFaders()` for external callers. If a native participant and a legacy fader share the same logical fader key, the native participant owns the visible control; the legacy participant is retained for diagnostics with `supersededBy` and an `overshadowed` bridge hit. Removal gates for the bridge are: native providers cover bundled mixer integrations, diagnostics show no unexpected legacy hits in normal playback, and repeated plugin hydration does not create duplicate faders.
|
||||
|
||||
Audio-mix diagnostics live under `slopsmith.audio_session.diagnostics.v1`. The `audio-mix` domain snapshot includes session state, participants, visible fader summaries, required participant-kind coverage, route summary, analyser summary, bridge hits, and bounded recent outcomes. Fader outcomes include operation name, participant id, fader id, status such as `committed`, `normalized`, `unavailable`, or `timeout`, and a bounded reason. Diagnostics must not include raw audio buffers, FFT arrays, device labels, stable hardware identifiers, secrets, or unredacted local paths; route/analyser payloads are summaries only.
|
||||
Audio-mix diagnostics live under `feedBack.audio_session.diagnostics.v1`. The `audio-mix` domain snapshot includes session state, participants, visible fader summaries, required participant-kind coverage, route summary, analyser summary, bridge hits, and bounded recent outcomes. Fader outcomes include operation name, participant id, fader id, status such as `committed`, `normalized`, `unavailable`, or `timeout`, and a bounded reason. Diagnostics must not include raw audio buffers, FFT arrays, device labels, stable hardware identifiers, secrets, or unredacted local paths; route/analyser payloads are summaries only.
|
||||
|
||||
For `audio-input`, native providers register source summaries with `sourceId`, `providerId`, `logicalSourceKey`, `kind`, redaction-safe label/pseudonym, `availability`, `channelSummary`, `sourceMode`, and provider operations. The public command surface is `inspect`, `list-sources`, `register-source`, `unregister-source`, `select-source`, `open-source`, and `close-source`; provider operations are `source.enumerate`, `source.describe`, `source.open`, and `source.close`. `inspect`, `list-sources`, and `select-source` are prompt-free and never open live input or call enumeration. `source.enumerate` runs only when explicitly requested by provider/user discovery. `open-source` is the permission boundary: it routes to `source.open`, attributes the requester, checks the selected source and requested channel shape, and records `handled`, `denied`, `degraded`, `failed`, `no-owner`, `no-handler`, `unsupported-command`, or `incompatible-version` outcomes.
|
||||
|
||||
@@ -109,9 +109,9 @@ Core also owns the durable public mapping index at `/api/audio-effects/mappings`
|
||||
|
||||
Providers register stable `providerId`, `pluginId`, `routeKey`, priority, availability, source mode, operations, and operation handlers. Executors register stable `executorId`, `pluginId`, `routeKey`, priority, availability, source mode, supported provider ids, supported stage kinds, optional maximum stage count, operations, and handlers. The host chooses the highest-priority enabled provider for a route unless the caller requests a specific provider, then chooses the highest-priority compatible executor for that provider and resolved plan. Compatibility means both provider-compatible and plan-compatible: a browser/WASM NAM executor can advertise `providerIds: ["nam-tone"]`, `supportedKinds: ["nam", "ir"]`, and `maxStages: 2`, so it will not be asked to execute a Rig Builder VST/full-chain plan. If a selected provider has no compatible executor and the caller supplies a fallback provider, the host may fall back to that provider; if the caller explicitly requested the original provider, the host reports `unavailable` instead of silently changing providers. The initial default route is `desktop-main`, matching the desktop native executor path planned for full-chain NAM/IR/VST playback while still allowing browser executors for non-Desktop runtimes.
|
||||
|
||||
`chain.resolve` returns schema `slopsmith.audio_effects.chain_plan.v1`. A valid plan includes `planId`, `routeKey`, `providerId`, `stages`, optional `segments`, and optional redaction-safe summaries. Each stage exposes only stable opaque `stageId`, `kind` (`nam`, `ir`, `vst`, `utility`, or `bypass`), `role` (`pre-pedal`, `amp`, `cab`, `rack`, `master-pre`, etc.), opaque `assetRef`, optional opaque `stateRef`, bypass state, gain summary, and safe summary metadata. Raw file paths, URLs, model filenames, IR filenames, VST state blobs, native preset JSON, callbacks, handles, DOM nodes, audio buffers, samples, and waveform data are rejected or omitted.
|
||||
`chain.resolve` returns schema `feedBack.audio_effects.chain_plan.v1`. A valid plan includes `planId`, `routeKey`, `providerId`, `stages`, optional `segments`, and optional redaction-safe summaries. Each stage exposes only stable opaque `stageId`, `kind` (`nam`, `ir`, `vst`, `utility`, or `bypass`), `role` (`pre-pedal`, `amp`, `cab`, `rack`, `master-pre`, etc.), opaque `assetRef`, optional opaque `stateRef`, bypass state, gain summary, and safe summary metadata. Raw file paths, URLs, model filenames, IR filenames, VST state blobs, native preset JSON, callbacks, handles, DOM nodes, audio buffers, samples, and waveform data are rejected or omitted.
|
||||
|
||||
Diagnostics live under `slopsmith.audio_effects.diagnostics.v1`. The snapshot includes provider summaries, executor summaries, route summaries, bridge hits, bounded recent outcomes, limits, and redaction notes. It intentionally omits full chain plans, stage asset references, provider-private mapping payloads, raw filenames, and song keys; diagnostics should explain which provider/executor/route failed without leaking local library structure or licensed asset names. Legacy NAM Tone/Rig Builder fetch interception, direct Desktop `loadPreset` calls, legacy tone controls, old `nam_tone.db` `tone_mappings` access, and MIDI/external effect handoffs are attributed through `audio-effects.legacy-nam-routing`, `audio-effects.legacy-native-load`, `audio-effects.legacy-tone-controls`, `audio-effects.legacy-tone-db`, and `audio-effects.legacy-midi-amp` bridge records while providers migrate.
|
||||
Diagnostics live under `feedBack.audio_effects.diagnostics.v1`. The snapshot includes provider summaries, executor summaries, route summaries, bridge hits, bounded recent outcomes, limits, and redaction notes. It intentionally omits full chain plans, stage asset references, provider-private mapping payloads, raw filenames, and song keys; diagnostics should explain which provider/executor/route failed without leaking local library structure or licensed asset names. Legacy NAM Tone/Rig Builder fetch interception, direct Desktop `loadPreset` calls, legacy tone controls, old `nam_tone.db` `tone_mappings` access, and MIDI/external effect handoffs are attributed through `audio-effects.legacy-nam-routing`, `audio-effects.legacy-native-load`, `audio-effects.legacy-tone-controls`, `audio-effects.legacy-tone-db`, and `audio-effects.legacy-midi-amp` bridge records while providers migrate.
|
||||
|
||||
## Playback Control Plane
|
||||
|
||||
@@ -119,7 +119,7 @@ The playback slice promotes `playback` as a core-owned command domain implemente
|
||||
|
||||
`static/app.js` remains the transport data plane. It registers a private playback adapter that can start songs, pause/resume/stop, seek, and manage loops, but the capability snapshot never exposes the `<audio>` element, JUCE player object, raw audio buffers, native route handles, samples, waveforms, recordings, local file paths, or URL payloads. Exported diagnostics use pseudonymous `target-*` ids for arrangement-scoped identity and hashed `settings-*` keys for per-song plugin settings; the local Capability Inspector may show visible title, artist, and arrangement labels for the active song.
|
||||
|
||||
Legacy playback surfaces remain supported during migration and are attributed through bridges such as `playback.window-play-song`, `playback.song-events`, `playback.window-slopsmith-transport`, `playback.loop-api`, and native route handoff records. Fresh audible `start` commands require `authorization: "user-action"`; background requesters may inspect or control an existing session, but user-priority pause/stop decisions block lower-priority automation until a user action resumes or starts a new session.
|
||||
Legacy playback surfaces remain supported during migration and are attributed through bridges such as `playback.window-play-song`, `playback.song-events`, `playback.window-feedBack-transport`, `playback.loop-api`, and native route handoff records. Fresh audible `start` commands require `authorization: "user-action"`; background requesters may inspect or control an existing session, but user-priority pause/stop decisions block lower-priority automation until a user action resumes or starts a new session.
|
||||
|
||||
## Progression Domain
|
||||
|
||||
@@ -127,7 +127,7 @@ The progression slice (spec 010) promotes `progression` as a core-owned command
|
||||
|
||||
The public command surface is `inspect`, `record-event`, `list-shop`, `buy-item`, and `equip-item`. `record-event` accepts only whitelisted externally-postable event types (`minigame_run` in v1); `song_completed` is server-derived inside `/api/stats` so scored-session authority stays in one place and is denied at this surface. `buy-item` and `equip-item` require `authorization: "user-action"`. Backend plugins use the symmetric plugin-context hook `record_progression_event` (the minigames hub reports runs through it), which trusts backend code and skips the HTTP whitelist.
|
||||
|
||||
The domain emits `challenge-completed`, `quest-completed`, `path-level-up`, `rank-changed`, `db-changed`, `calibration-completed`, and `cosmetic-equipped` on the capability surface, mirrored as `progression:*` events on `window.slopsmith` for non-capability consumers. Diagnostics live under `slopsmith.progression.diag.v1` and contain content-load warnings, rank/path-level/quest counts, and wallet totals only — no song filenames or display names.
|
||||
The domain emits `challenge-completed`, `quest-completed`, `path-level-up`, `rank-changed`, `db-changed`, `calibration-completed`, and `cosmetic-equipped` on the capability surface, mirrored as `progression:*` events on `window.feedBack` for non-capability consumers. Diagnostics live under `feedBack.progression.diag.v1` and contain content-load warnings, rank/path-level/quest counts, and wallet totals only — no song filenames or display names.
|
||||
|
||||
Decibels are earned exclusively by playing (songs, minigame runs, quest rewards); there is no real-money acquisition path and none may be added. The wallet tracks spend separately from the monotonic lifetime-earned total, so per-source XP resets and `db_earned` goals stay correct. A deferred release slice adds a `contributor` role so plugins can ship their own challenge/quest content (e.g. a drums plugin contributing drums challenges); content stays core-bundled until then.
|
||||
|
||||
@@ -137,11 +137,11 @@ The visualization slice (cap:6) promotes `visualization` as a core-owned provide
|
||||
|
||||
The public command surface is `inspect`, `list-providers`, `select-renderer`, and `clear-renderer`. Selection delegates to the existing picker (`setViz`) so localStorage persistence, WebGL2 gating, and fallback semantics have exactly one implementation. The domain emits `providers-refreshed`, `renderer-changed` (with a `source` of `auto-match`, `user-select`, `fallback`, or `command:<requester>`), `renderer-ready`, and `renderer-failed`.
|
||||
|
||||
Provider discovery is still the legacy surface — `type: "visualization"` manifests populate the picker and `window.slopsmithViz_*` factory globals carry the renderer contract — and both are registered as compatibility shims (`visualization:type-visualization-manifest`, `visualization:window.slopsmithViz_*`) with hit accounting, so the Inspector shows exactly how much of the domain still rides the bridge. Plugins migrate by declaring a `visualization` provider capability in their manifests; the renderer factory contract (`init`/`draw`/`resize`/`destroy`, `contextType`, `matchesArrangement`) is unchanged.
|
||||
Provider discovery is still the legacy surface — `type: "visualization"` manifests populate the picker and `window.feedBackViz_*` factory globals carry the renderer contract — and both are registered as compatibility shims (`visualization:type-visualization-manifest`, `visualization:window.feedBackViz_*`) with hit accounting, so the Inspector shows exactly how much of the domain still rides the bridge. Plugins migrate by declaring a `visualization` provider capability in their manifests; the renderer factory contract (`init`/`draw`/`resize`/`destroy`, `contextType`, `matchesArrangement`) is unchanged.
|
||||
|
||||
**Per-instance provider settings (#849).** A provider may declare a `settings` array on its `visualization` capability — generic control descriptors (`{ key, label, type: "toggle" | "range" | "select", default, min/max/step, options }`) the capability-pipelines schema validates on *any* domain (the field lives on the shared `capabilityDeclaration`, not a visualization-only spot — see `docs/plugin-manifest.schema.json`). Descriptors flow through the **generic participant model**: the backend validates them for `/api/plugins` (`plugins/__init__.py`), `static/capabilities.js` normalizes + preserves them on the registered participant (so generic `inspect('visualization')` carries them), and the visualization owner reads them back from the participant by id — no app.js/picker side channel. They surface in the `list-providers` snapshot (each provider's `settings`, deep-frozen) plus a `provider_policy.hasSettings` flag in diagnostics, so a consuming host — splitscreen's per-panel control popover — can render the controls generically without per-plugin hardcoding. The visualization domain's **apply contract**: a provider that declares `settings` MUST implement `applySetting(key, value)` on its renderer instance (the host calls it on the specific per-panel instance, which is inherently per-panel — no canvas→panel resolution, no shared global keys); `getSetting(key)` is optional (the host falls back to the declared `default`). The host owns persistence. **This core slice lands the declarative surface + participant plumbing only** — no bundled provider declares `settings` yet (`highway_3d` still ships the legacy `factory.panelControls` static). The `highway_3d` migration and the splitscreen generic consumer are the remaining #849 follow-ups.
|
||||
|
||||
Diagnostics live under `slopsmith.visualization_capability.v1` and contain provider ids/labels/context types, the active renderer id and its selection source, the last auto-match outcome (resolved id + whether any predicate claimed the song), and the last failure (provider id + reason) — never song filenames, titles, or arrangement names. Per-panel selection (splitscreen #90) and per-panel provider settings (#849) are tracked follow-ups; the domain currently models the primary highway surface.
|
||||
Diagnostics live under `feedBack.visualization_capability.v1` and contain provider ids/labels/context types, the active renderer id and its selection source, the last auto-match outcome (resolved id + whether any predicate claimed the song), and the last failure (provider id + reason) — never song filenames, titles, or arrangement names. Per-panel selection (splitscreen #90) and per-panel provider settings (#849) are tracked follow-ups; the domain currently models the primary highway surface.
|
||||
|
||||
## Note-Detection Domain
|
||||
|
||||
@@ -151,7 +151,7 @@ The public command surface is `inspect`, `register-provider`, `unregister-provid
|
||||
|
||||
The legacy chart-coupled surface — `highway.setNoteStateProvider(fn)`, the single-global-detector path spec 009 retires — keeps working unchanged and is wrapped for compatibility-shim hit accounting (`note-detection:highway.setNoteStateProvider`). Migrating the chart `note_detect` consumer, Step Mode verify, minigames YIN scoring, and the `setVerifyTarget` bridge onto real bindings — and wiring per-binding tuning contexts into the engine verifier — is the remainder of the spec-009 slice and lands behind the Spec 003 migration gate.
|
||||
|
||||
Diagnostics live under `slopsmith.note_detection_capability.v1` and contain provider ids/labels/kinds, binding summaries (requester, provider, redacted context, target size), availability, and the last bounded outcome (event, binding, provider, MIDI number, hit flag) — never raw audio buffers, sample data, device labels, or song identity.
|
||||
Diagnostics live under `feedBack.note_detection_capability.v1` and contain provider ids/labels/kinds, binding summaries (requester, provider, redacted context, target size), availability, and the last bounded outcome (event, binding, provider, MIDI number, hit flag) — never raw audio buffers, sample data, device labels, or song identity.
|
||||
|
||||
## MIDI-Input Domain
|
||||
|
||||
@@ -159,11 +159,11 @@ The MIDI-input slice (spec 012, issues #873/#880) promotes `midi-input` as a **c
|
||||
|
||||
Native providers register source summaries with `providerId`, a stable `sourceId`, a derived redaction-safe `logicalSourceKey` (`providerId::sourceId`), `kind: "midi"`, a label, and `availability`. The public command surface is `inspect`, `list-sources`, `discover`, `select-source`, `open-source`, and `close-source`; provider operations are `source.enumerate`, `source.describe`, `source.open`, and `source.close`. `inspect`, `list-sources`, and `select-source` are prompt-free and never request MIDI access. Unlike audio (where `getUserMedia` gates labels and `open-source` is the prompt), Web-MIDI's `requestMIDIAccess()` gates the whole input list, so **`discover` is the permission boundary** and records `denied`/`unavailable` outcomes; `open-source` then attaches a shared listener session and never re-prompts.
|
||||
|
||||
Selected input is persisted by `logicalSourceKey` (`slopsmith.midiInput.selectedLogicalSourceKey`) when browser storage is available. Compatible requesters share one open session per source; each later calls `close-source`, and the provider receives `source.close` only after the last requester releases. Live MIDI message delivery (for the "play a note / hit a pad" calibration check) is exposed to in-page consumers through the public `window.slopsmith.midiInput` session handle only — never as raw capability events or diagnostics.
|
||||
Selected input is persisted by `logicalSourceKey` (`feedBack.midiInput.selectedLogicalSourceKey`) when browser storage is available. Compatible requesters share one open session per source; each later calls `close-source`, and the provider receives `source.close` only after the last requester releases. Live MIDI message delivery (for the "play a note / hit a pad" calibration check) is exposed to in-page consumers through the public `window.feedBack.midiInput` session handle only — never as raw capability events or diagnostics.
|
||||
|
||||
The reserved `midi-control` domain is the planned **sibling** for control mappings (CC/pitchbend/note → action routing) and will consume `midi-input` for device access (spec 013 / #882); this slice carves the device control plane out so `midi-control` can stay mappings-only. `midi-control` stays RESERVED (documentation-only) until a concrete mapping consumer + tests exist, per the future-domain governance.
|
||||
|
||||
Diagnostics live under `slopsmith.midi_input.diagnostics.v1` and contain provider ids, source ids/keys/kinds/availability, the selected key, and open-session keys — **device labels are redacted** and no raw MIDI messages are ever included.
|
||||
Diagnostics live under `feedBack.midi_input.diagnostics.v1` and contain provider ids, source ids/keys/kinds/availability, the selected key, and open-session keys — **device labels are redacted** and no raw MIDI messages are ever included.
|
||||
|
||||
## Capability Roles
|
||||
|
||||
@@ -185,11 +185,11 @@ Use capability declarations for provider/requester/observer relationships:
|
||||
|
||||
Future app-level workflows can then express intent through capability domains instead of hard-coding plugin-private implementation details.
|
||||
|
||||
Core registers manifest capability declarations from `/api/plugins` before plugin scripts hydrate. Runtime owners can then re-register the same participant with command handlers, event handlers, and current availability state. The merged participant view is visible through `window.slopsmith.capabilities.snapshotDiagnostics()` and `getDiagnostics()`.
|
||||
Core registers manifest capability declarations from `/api/plugins` before plugin scripts hydrate. Runtime owners can then re-register the same participant with command handlers, event handlers, and current availability state. The merged participant view is visible through `window.feedBack.capabilities.snapshotDiagnostics()` and `getDiagnostics()`.
|
||||
|
||||
Core domains include review metadata in diagnostics:
|
||||
|
||||
- `active`: wired to current Slopsmith behavior and expected to work as an integration point.
|
||||
- `active`: wired to current FeedBack behavior and expected to work as an integration point.
|
||||
- `diagnostic`: support/inspection-only runtime surfaces.
|
||||
|
||||
PR1 includes only the delivered domains listed in [capability-roadmap.md](capability-roadmap.md): `pipeline`, `diagnostics`, and `library`. The follow-up audio graph/session slice promotes `audio-mix`, `audio-input`, `audio-monitoring`, and a coordinated `stems` surface. The playback slice promotes `playback` as an active transport control plane. The audio-effects slice promotes provider-selected effect-chain planning while leaving physical processor loading to compatible executors such as trusted Desktop native audio or a browser/WASM executor. The visualization slice promotes `visualization` as the highway renderer provider-coordinator, and the note-detection slice (spec 009) promotes `note-detection` as the detection-binding control plane. Backend routes, app UI, settings, and other hardware-facing domains remain documented in the roadmap and safety matrix until their own host workflow/provider slice exists.
|
||||
@@ -201,7 +201,7 @@ Capability metadata is versioned by the `capability-pipelines.v1` standard. Inva
|
||||
Requesters should use the public claim/dispatch/release flow instead of mutating another plugin's globals:
|
||||
|
||||
```js
|
||||
const api = window.slopsmith.capabilities;
|
||||
const api = window.feedBack.capabilities;
|
||||
const releaseClaim = api.claim({ capability: 'example.plugin-domain', claimId: 'example.automation-active', requester: 'example_requester' });
|
||||
await api.dispatch({
|
||||
capability: 'example.plugin-domain',
|
||||
@@ -244,9 +244,9 @@ Dispatch results use explicit outcomes: `handled`, `transformed`, `denied`, `fai
|
||||
|
||||
## Deferred Core Adapters
|
||||
|
||||
UI placement and settings contributions are real Slopsmith surfaces, but they are not PR1 capability contracts (visualization is active as of the cap:6 slice; note-detection as of the spec-009 slice). Audio mixer/session domains are active as of the audio graph/session slice, playback is active as of the playback control-plane slice, and audio-effects is active as a provider/route/chain-plan coordinator; plugins should keep using current documented APIs for remaining areas until the corresponding domain PR ships the host workflow, command/event contract, compatibility shims, diagnostics fields, and tests.
|
||||
UI placement and settings contributions are real FeedBack surfaces, but they are not PR1 capability contracts (visualization is active as of the cap:6 slice; note-detection as of the spec-009 slice). Audio mixer/session domains are active as of the audio graph/session slice, playback is active as of the playback control-plane slice, and audio-effects is active as a provider/route/chain-plan coordinator; plugins should keep using current documented APIs for remaining areas until the corresponding domain PR ships the host workflow, command/event contract, compatibility shims, diagnostics fields, and tests.
|
||||
|
||||
The library provider workflow is the PR1 core adapter and is implemented natively as the `library` capability module. Provider refresh, selection, and sync run through `library` owner commands; backend provider registration remains the way providers enter the library registry, and the browser module turns that registry into provider participants. The app event bus continues to dispatch local `window.slopsmith` events for legacy listeners; playback now mirrors song transport, route, seek, and loop lifecycle into `playback`, and visualization attributes renderer selection/failure, while navigation, note, and route-only surfaces remain outside capability domains until their own slices land.
|
||||
The library provider workflow is the PR1 core adapter and is implemented natively as the `library` capability module. Provider refresh, selection, and sync run through `library` owner commands; backend provider registration remains the way providers enter the library registry, and the browser module turns that registry into provider participants. The app event bus continues to dispatch local `window.feedBack` events for legacy listeners; playback now mirrors song transport, route, seek, and loop lifecycle into `playback`, and visualization attributes renderer selection/failure, while navigation, note, and route-only surfaces remain outside capability domains until their own slices land.
|
||||
|
||||
The direct `window.highway` object remains the renderer data plane. Per-frame reads such as notes, chords, beats, and renderer hooks should not be moved behind asynchronous capability commands until there is a dedicated chart/render facade.
|
||||
|
||||
@@ -254,11 +254,11 @@ The direct `window.highway` object remains the renderer data plane. Per-frame re
|
||||
|
||||
Large management surfaces should prefer plugin-owned UI over crowding normal Settings. First-party management plugins can contribute screens and settings panels while core keeps shared services and diagnostics contracts centralized.
|
||||
|
||||
The bundled Capability Inspector plugin is the support surface for the current graph. It reads `window.slopsmith.capabilities.snapshotDiagnostics()`, filters by domain, and summarizes manifest participants, runtime participants, conflicts, unsupported versions, safety classes, expected legacy event surfaces, and compatibility shim hits without rendering raw runtime objects. Domains are grouped in review order: application/library, player/audio runtime, plugin-defined surfaces, then capability runtime. In the all-domains view, each domain starts collapsed with a domain-specific icon plus compact summary badges for participant-lane count, endpoint count, observed links, shimmed links, and status; badge labels live in tooltips/ARIA labels so the header stays scannable. Clicking the domain label expands or collapses the domain, opening the same graph view used by the single-domain filter. The graph places owner details and right-aligned command/event groups on the left, with short owner descriptions bottom-aligned as the final part of that pane. Participant usage is grouped the same way on the right, with observed or shimmed links between border-aligned endpoint ports. In multi-provider domains, links to provider participants use provider-family colors: purple for owner-to-provider command delegation and a lighter violet for provider events. Provider participants, including `library` sources, stay on the right lane and show a provider icon in their header. Headers show role-aware core/non-core origin badges such as Core owner, Core provider, or Non-core participant; owner headers place the origin badge directly after the owner icon, and the built-in local library provider is marked as core-origin. Observer and requester roles are implied by the command/event links rather than separate header badges. Participant cards are shown only when the plugin or runtime source has visible command or event usage for the current graph filter; domains with no such usage show zero participants, and attribution-only shims with no matching endpoint stay out of the lane. Command and event groups can collapse; when collapsed, all links for that side and group converge on the single group port. Hovering a participant, endpoint, or command/event group emphasizes the matching links and dims unrelated links; owner-side labels outside the current focus de-emphasize so the active source endpoints are easy to track. Expanded domain graphs progressively enhance to Cytoscape.js overlays that route bezier links between measured DOM endpoint ports, while keeping the HTML lanes as the fallback and readable data surface. Its Plugins-menu entry is hidden by default; enable **Capability Inspector → Show in Plugins menu** from Settings when reviewing or debugging capability behavior.
|
||||
The bundled Capability Inspector plugin is the support surface for the current graph. It reads `window.feedBack.capabilities.snapshotDiagnostics()`, filters by domain, and summarizes manifest participants, runtime participants, conflicts, unsupported versions, safety classes, expected legacy event surfaces, and compatibility shim hits without rendering raw runtime objects. Domains are grouped in review order: application/library, player/audio runtime, plugin-defined surfaces, then capability runtime. In the all-domains view, each domain starts collapsed with a domain-specific icon plus compact summary badges for participant-lane count, endpoint count, observed links, shimmed links, and status; badge labels live in tooltips/ARIA labels so the header stays scannable. Clicking the domain label expands or collapses the domain, opening the same graph view used by the single-domain filter. The graph places owner details and right-aligned command/event groups on the left, with short owner descriptions bottom-aligned as the final part of that pane. Participant usage is grouped the same way on the right, with observed or shimmed links between border-aligned endpoint ports. In multi-provider domains, links to provider participants use provider-family colors: purple for owner-to-provider command delegation and a lighter violet for provider events. Provider participants, including `library` sources, stay on the right lane and show a provider icon in their header. Headers show role-aware core/non-core origin badges such as Core owner, Core provider, or Non-core participant; owner headers place the origin badge directly after the owner icon, and the built-in local library provider is marked as core-origin. Observer and requester roles are implied by the command/event links rather than separate header badges. Participant cards are shown only when the plugin or runtime source has visible command or event usage for the current graph filter; domains with no such usage show zero participants, and attribution-only shims with no matching endpoint stay out of the lane. Command and event groups can collapse; when collapsed, all links for that side and group converge on the single group port. Hovering a participant, endpoint, or command/event group emphasizes the matching links and dims unrelated links; owner-side labels outside the current focus de-emphasize so the active source endpoints are easy to track. Expanded domain graphs progressively enhance to Cytoscape.js overlays that route bezier links between measured DOM endpoint ports, while keeping the HTML lanes as the fallback and readable data surface. Its Plugins-menu entry is hidden by default; enable **Capability Inspector → Show in Plugins menu** from Settings when reviewing or debugging capability behavior.
|
||||
|
||||
## Diagnostics Contract
|
||||
|
||||
Capability diagnostics use schema `slopsmith.capabilities.diagnostics.v1`. Snapshots are redaction-safe and capped at 64 KB by trimming older `recentDecisions` first while preserving current participants, active or orphaned claims, conflicts, domain review metadata, shim summaries, safety notes, and unsupported-version reports. Server diagnostics bundles include plugin manifest capability metadata, validation warnings, unsupported-version metadata, and compatibility shim summaries.
|
||||
Capability diagnostics use schema `feedBack.capabilities.diagnostics.v1`. Snapshots are redaction-safe and capped at 64 KB by trimming older `recentDecisions` first while preserving current participants, active or orphaned claims, conflicts, domain review metadata, shim summaries, safety notes, and unsupported-version reports. Server diagnostics bundles include plugin manifest capability metadata, validation warnings, unsupported-version metadata, and compatibility shim summaries.
|
||||
|
||||
Compatibility shim entries include `shimId`, `source`, `capability`, `legacySurface`, `status`, `reason`, and optional hit fields. A shim with `hitCount > 0` means legacy behavior was observed, not merely declared. The `library` domain no longer uses compatibility shims for provider registration or source selection; provider attribution comes from `owner_plugin_id` and runtime provider participants. Future domains should add expected shim entries only in the PR that implements their actual legacy bridge.
|
||||
|
||||
@@ -274,10 +274,10 @@ Future privileged domains must state user value, included and excluded commands,
|
||||
|
||||
## Rehydration Pattern
|
||||
|
||||
Plugins that wrap shared functions such as `window.playSong` or `window.showScreen` should store wrapper state on a stable `window.__slopsmith...Hooks` object. Re-running the script should replace the implementation object and return before installing another wrapper.
|
||||
Plugins that wrap shared functions such as `window.playSong` or `window.showScreen` should store wrapper state on a stable `window.__feedBack...Hooks` object. Re-running the script should replace the implementation object and return before installing another wrapper.
|
||||
|
||||
```js
|
||||
const hookState = window.__slopsmithMyPluginHooks || (window.__slopsmithMyPluginHooks = {});
|
||||
const hookState = window.__feedBackMyPluginHooks || (window.__feedBackMyPluginHooks = {});
|
||||
hookState.impl = { afterPlaySong(filename) { /* current implementation */ } };
|
||||
if (hookState.installed) return;
|
||||
hookState.installed = true;
|
||||
@@ -290,7 +290,7 @@ window.playSong = async function(filename, arrangement) {
|
||||
|
||||
## Validation Commands
|
||||
|
||||
From the `slopsmith/` directory:
|
||||
From the `feedBack/` directory:
|
||||
|
||||
```bash
|
||||
node --check static/app.js
|
||||
|
||||
+18
-18
@@ -1,6 +1,6 @@
|
||||
# Capability Authoring Recipes
|
||||
|
||||
Use these examples as small manifest fragments when migrating plugin-facing integrations to capability pipelines. The capability model is system-wide; these recipes focus on plugin manifests because core-owned domains are registered by Slopsmith itself. Each example is intentionally complete enough to pass the loader contract in [plugin-manifest.schema.json](plugin-manifest.schema.json).
|
||||
Use these examples as small manifest fragments when migrating plugin-facing integrations to capability pipelines. The capability model is system-wide; these recipes focus on plugin manifests because core-owned domains are registered by FeedBack itself. Each example is intentionally complete enough to pass the loader contract in [plugin-manifest.schema.json](plugin-manifest.schema.json).
|
||||
|
||||
> **Self-hosted CSS?** If your plugin uses Tailwind classes core doesn't ship (notably arbitrary values like `text-[11px]`), declare a `styles` key and bundle your own preflight-off stylesheet — see [plugin-styles.md](plugin-styles.md). That is separate from the capability-pipeline recipes below.
|
||||
|
||||
@@ -124,7 +124,7 @@ A route-only wrapper that uses the library capability without registering a brow
|
||||
|
||||
## Audio Mix Fader Provider
|
||||
|
||||
Existing plugins can keep using `window.slopsmith.audio.registerFader(spec)` while migrating. The compatibility bridge records the fader as an `audio-mix` participant. New bundled code should prefer a native participant declaration plus the audio-session helper once available in its integration point.
|
||||
Existing plugins can keep using `window.feedBack.audio.registerFader(spec)` while migrating. The compatibility bridge records the fader as an `audio-mix` participant. New bundled code should prefer a native participant declaration plus the audio-session helper once available in its integration point.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -147,11 +147,11 @@ Existing plugins can keep using `window.slopsmith.audio.registerFader(spec)` whi
|
||||
|
||||
Native audio-mix fader providers should register a stable participant id and fader id, return the committed value from every set operation, and settle get/set operations within two seconds. The player mixer displays the committed value rather than the raw requested value. If the fader is temporarily unavailable, keep the participant registered with unavailable/disabled state so the mixer can render a disabled control and diagnostics can explain why it cannot be changed.
|
||||
|
||||
During migration, a plugin may still call `window.slopsmith.audio.registerFader(spec)`. Core maps that legacy fader into a compatibility-backed audio-mix participant and records bridge hits. If a native participant and a legacy fader represent the same logical source, the native participant owns the visible control and the legacy path is reported as compatibility-backed/overshadowed.
|
||||
During migration, a plugin may still call `window.feedBack.audio.registerFader(spec)`. Core maps that legacy fader into a compatibility-backed audio-mix participant and records bridge hits. If a native participant and a legacy fader represent the same logical source, the native participant owns the visible control and the legacy path is reported as compatibility-backed/overshadowed.
|
||||
|
||||
## Audio Effects Provider
|
||||
|
||||
Plugins that can provide guitar/bass processing chains should declare `audio-effects` as a provider and register at runtime with `window.slopsmith.audioEffects.registerProvider(...)`. The provider returns opaque chain plans; it must not expose local filenames, URLs, native preset JSON, VST state blobs, or raw handles through diagnostics or public route state.
|
||||
Plugins that can provide guitar/bass processing chains should declare `audio-effects` as a provider and register at runtime with `window.feedBack.audioEffects.registerProvider(...)`. The provider returns opaque chain plans; it must not expose local filenames, URLs, native preset JSON, VST state blobs, or raw handles through diagnostics or public route state.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -173,7 +173,7 @@ Plugins that can provide guitar/bass processing chains should declare `audio-eff
|
||||
```
|
||||
|
||||
```js
|
||||
const effects = window.slopsmith && window.slopsmith.audioEffects;
|
||||
const effects = window.feedBack && window.feedBack.audioEffects;
|
||||
effects.registerProvider({
|
||||
providerId: 'rig-builder',
|
||||
pluginId: 'rig_builder',
|
||||
@@ -184,7 +184,7 @@ effects.registerProvider({
|
||||
'chain.resolve': request => ({
|
||||
outcome: 'handled',
|
||||
plan: {
|
||||
schema: 'slopsmith.audio_effects.chain_plan.v1',
|
||||
schema: 'feedBack.audio_effects.chain_plan.v1',
|
||||
planId: 'song-tone-plan',
|
||||
routeKey: request.routeKey,
|
||||
providerId: 'rig-builder',
|
||||
@@ -203,14 +203,14 @@ effects.registerProvider({
|
||||
User-facing controls should dispatch through the domain instead of mutating another plugin's private state:
|
||||
|
||||
```js
|
||||
await window.slopsmith.capabilities.dispatch({
|
||||
await window.feedBack.capabilities.dispatch({
|
||||
capability: 'audio-effects',
|
||||
command: 'select-chain',
|
||||
source: 'rig_builder',
|
||||
payload: { routeKey: 'desktop-main', providerId: 'rig-builder', authorization: 'user-action' }
|
||||
});
|
||||
|
||||
const resolved = await window.slopsmith.capabilities.dispatch({
|
||||
const resolved = await window.feedBack.capabilities.dispatch({
|
||||
capability: 'audio-effects',
|
||||
command: 'resolve-plan',
|
||||
source: 'nam_tone',
|
||||
@@ -221,7 +221,7 @@ const resolved = await window.slopsmith.capabilities.dispatch({
|
||||
Providers should store public song/tone routing through the host-owned mapping index and keep their own preset or chain rows private. The mapping's `provider_ref` is opaque to core: NAM Tone can use a preset id, Rig Builder can use a chain/preset id, and each provider resolves that reference in `chain.resolve`.
|
||||
|
||||
```js
|
||||
await window.slopsmith.audioEffects.upsertMapping({
|
||||
await window.feedBack.audioEffects.upsertMapping({
|
||||
song_key: playbackTarget.settingsKey,
|
||||
filename: playbackTarget.filename, // optional migration/debug context
|
||||
tone_key: 'Dist',
|
||||
@@ -232,7 +232,7 @@ await window.slopsmith.audioEffects.upsertMapping({
|
||||
active: true
|
||||
});
|
||||
|
||||
const mappings = await window.slopsmith.audioEffects.listMappings({
|
||||
const mappings = await window.feedBack.audioEffects.listMappings({
|
||||
song_key: playbackTarget.settingsKey,
|
||||
tone_key: 'Dist'
|
||||
});
|
||||
@@ -243,7 +243,7 @@ Only one mapping is active for a `song_key + tone_key` at a time, but multiple p
|
||||
Browser or native executors should declare both provider scope and plan scope. A NAM-only browser executor should not claim Rig Builder plans just because it can load NAM files:
|
||||
|
||||
```js
|
||||
window.slopsmith.audioEffects.registerExecutor({
|
||||
window.feedBack.audioEffects.registerExecutor({
|
||||
executorId: 'nam-tone-browser-wasm',
|
||||
pluginId: 'nam_tone',
|
||||
routeKey: 'desktop-main',
|
||||
@@ -296,7 +296,7 @@ Plugins that need live instrument input should declare requester/observer intent
|
||||
Requesters should list or inspect sources before opening them. `inspect`, `list-sources`, and `select-source` are prompt-free and must not call provider enumeration or open live input. When a requester needs audio, it dispatches `open-source` with a purpose and required channel shape. The requester identity is taken from the dispatch `source` (the authenticated caller) — a payload-supplied `requesterId` is ignored, so a requester cannot spoof another's identity or release a shared session it does not own. Compatible requesters share one open session; each requester later dispatches `close-source`, and the provider is closed only after the last requester releases it.
|
||||
|
||||
```js
|
||||
const api = window.slopsmith.capabilities;
|
||||
const api = window.feedBack.capabilities;
|
||||
await api.dispatch({ capability: 'audio-input', command: 'select-source', source: 'user', payload: { logicalSourceKey: 'browser:instrument:primary' } });
|
||||
const opened = await api.dispatch({
|
||||
capability: 'audio-input',
|
||||
@@ -436,7 +436,7 @@ Plugins that need to inspect or coordinate song transport should declare `playba
|
||||
Fresh audible starts require a user action. Background plugins should call `inspect` first and attach to an existing compatible session; if a plugin needs to offer a play/start action, wire it to a visible user gesture and pass `authorization: "user-action"`.
|
||||
|
||||
```js
|
||||
const api = window.slopsmith.capabilities;
|
||||
const api = window.feedBack.capabilities;
|
||||
|
||||
const state = await api.dispatch({
|
||||
capability: 'playback',
|
||||
@@ -455,7 +455,7 @@ if (state.status !== 'idle') {
|
||||
}
|
||||
```
|
||||
|
||||
During migration, legacy uses of `window.playSong`, `song:*` events, `window.slopsmith.seek`, and loop helpers remain available and are recorded as playback bridge hits. Treat bridge hits as migration telemetry: native capability requests should eventually cover normal plugin workflows so unexpected legacy hits disappear from diagnostics.
|
||||
During migration, legacy uses of `window.playSong`, `song:*` events, `window.feedBack.seek`, and loop helpers remain available and are recorded as playback bridge hits. Treat bridge hits as migration telemetry: native capability requests should eventually cover normal plugin workflows so unexpected legacy hits disappear from diagnostics.
|
||||
|
||||
## Progression Requester And Observer
|
||||
|
||||
@@ -484,7 +484,7 @@ Plugins that report gameplay outcomes or react to player progression (spec 010)
|
||||
`buy-item` and `equip-item` require a visible user gesture (`authorization: "user-action"`). Decibels are play-earned only; plugins must not present any purchase path.
|
||||
|
||||
```js
|
||||
const api = window.slopsmith.capabilities;
|
||||
const api = window.feedBack.capabilities;
|
||||
|
||||
const result = await api.dispatch({
|
||||
capability: 'progression',
|
||||
@@ -494,14 +494,14 @@ const result = await api.dispatch({
|
||||
});
|
||||
// result.payload lists challenges/quests completed by this event (toast UX).
|
||||
|
||||
window.slopsmith.on('progression:quest-completed', (e) => {
|
||||
window.feedBack.on('progression:quest-completed', (e) => {
|
||||
console.log('quest done:', e.detail.title, '+' + e.detail.reward_db + ' dB');
|
||||
});
|
||||
```
|
||||
|
||||
## Future Expansion Domains
|
||||
|
||||
Some domain names are reserved for expected future contracts, but they are not registered in the runtime graph yet. For example, `ui.player-panels` is documented as a likely panel-host surface, but Slopsmith does not currently expose a capability command for panel contributions. See [capability-roadmap.md](capability-roadmap.md) for the PR1 domain set and deferred-domain checklist.
|
||||
Some domain names are reserved for expected future contracts, but they are not registered in the runtime graph yet. For example, `ui.player-panels` is documented as a likely panel-host surface, but FeedBack does not currently expose a capability command for panel contributions. See [capability-roadmap.md](capability-roadmap.md) for the PR1 domain set and deferred-domain checklist.
|
||||
|
||||
Plugins should not declare future expansion domains until the corresponding host workflow ships. For current integrations, prefer active domains such as `library`, `playback`, `audio-mix`, `audio-input`, `audio-monitoring`, or `stems` intent matching the recipes above.
|
||||
|
||||
@@ -537,7 +537,7 @@ the owner is visible in the Capability Inspector.
|
||||
Register the action from the plugin's `screen.js`:
|
||||
|
||||
```js
|
||||
window.slopsmith.libraryCardActions.register({
|
||||
window.feedBack.libraryCardActions.register({
|
||||
id: 'my_card_action.run',
|
||||
pluginId: 'my_card_action',
|
||||
label: 'Do the thing',
|
||||
|
||||
@@ -38,7 +38,7 @@ The audio graph/session and effects slices promote these domains after PR1:
|
||||
|
||||
`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-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.feedBack.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.
|
||||
|
||||
@@ -50,7 +50,7 @@ The focused audio-effects control-plane slice promotes provider registration, us
|
||||
|
||||
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.
|
||||
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.feedBack` 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.
|
||||
|
||||
@@ -82,7 +82,7 @@ This is the recommended order for UI/UX capability work only. It excludes audio
|
||||
| 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. |
|
||||
| 8 | Visualization UX | `visualization` | `type: "visualization"`, `window.feedBackViz_*`, 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. |
|
||||
|
||||
@@ -127,7 +127,7 @@ These candidate domains were surfaced by the included plugin inventory but are n
|
||||
| `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. |
|
||||
| `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 FeedBack 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.
|
||||
|
||||
@@ -141,7 +141,7 @@ PR1 does not add per-domain versioning. The `capability-pipelines.v1` standard v
|
||||
- Changing command payloads, return payloads, or dispatch outcomes incompatibly is breaking.
|
||||
- A breaking change requires either a future `capability-pipelines` version 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.
|
||||
Per-domain versions should wait until FeedBack has a concrete need for multiple incompatible versions of the same domain to coexist.
|
||||
|
||||
## Future Domain PR Checklist
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Capability declarations include a safety class so reviewers can decide whether a domain can ship as a normal plugin contract or needs extra enforcement first.
|
||||
|
||||
Core domains also have a review scope. **Active contract** domains are wired to current Slopsmith behavior and should be tested as working integration points. Expected future domains are documented below, but are intentionally not registered in the runtime graph until Slopsmith ships the corresponding host UI or provider workflow.
|
||||
Core domains also have a review scope. **Active contract** domains are wired to current FeedBack behavior and should be tested as working integration points. Expected future domains are documented below, but are intentionally not registered in the runtime graph until FeedBack ships the corresponding host UI or provider workflow.
|
||||
|
||||
| Domain | Owner Kind | Safety Class | Stable Commands | Provider Operations | Notes |
|
||||
|--------|------------|--------------|-----------------|---------------------|-------|
|
||||
@@ -14,10 +14,10 @@ Core domains also have a review scope. **Active contract** domains are wired to
|
||||
| audio-monitoring | provider-coordinator | sensitive | inspect, list-providers, register-provider, unregister-provider, select-provider, start, stop, set-direct-monitor | monitoring.start, monitoring.stop, monitoring.status, monitoring.set-direct-monitor | Inspect/list/select/status are prompt-free. Fresh monitoring start requires explicit user action; background requesters may only attach to an active compatible session. Outcomes distinguish handled, stopped, denied, unavailable, degraded, failed, no-owner, no-handler, unsupported-command, incompatible, incompatible-version, provider-selection-required, and user-action-required. Diagnostics redact raw device labels, hardware ids, paths, secrets, live handles, buffers, samples, waveforms, and recordings. |
|
||||
| stems | coordinator plus plugin provider | safe | inspect, mute, restore | stem.get-state, stem.apply-automation, stem.restore-automation | Core coordinates claims/overrides; the active Stems provider owns actual stem state/playback. |
|
||||
| playback | exclusive-owner | safe | inspect, start, pause, resume, stop, seek, set-loop, clear-loop, register-requester, register-observer | none | Core owns the transport control plane while `app.js` keeps raw media handles private. Fresh audible starts require explicit user action. Diagnostics expose pseudonymous targets, sanitized route/timing/loop state, requester/observer summaries, bridge hits, bounded recent outcomes, and no audio elements, native handles, decoded buffers, samples, waveforms, or recordings. |
|
||||
| progression | exclusive-owner | safe | inspect, record-event, list-shop, buy-item, equip-item | none | Core owns mastery rank, the challenge/quest engine, the Decibels wallet, and the cosmetics shop (spec 010). `record-event` accepts whitelisted types only (`minigame_run`); `song_completed` is server-derived in `/api/stats` and denied here. `buy-item`/`equip-item` require explicit user action. Decibels are play-earned only — no real-money path exists or may be added. Diagnostics (`slopsmith.progression.diag.v1`) carry content warnings, rank/level/quest counts, and wallet totals; no song filenames or display names. |
|
||||
| progression | exclusive-owner | safe | inspect, record-event, list-shop, buy-item, equip-item | none | Core owns mastery rank, the challenge/quest engine, the Decibels wallet, and the cosmetics shop (spec 010). `record-event` accepts whitelisted types only (`minigame_run`); `song_completed` is server-derived in `/api/stats` and denied here. `buy-item`/`equip-item` require explicit user action. Decibels are play-earned only — no real-money path exists or may be added. Diagnostics (`feedBack.progression.diag.v1`) carry content warnings, rank/level/quest counts, and wallet totals; no song filenames or display names. |
|
||||
| audio-effects | provider-coordinator | sensitive | inspect, list-providers, register-provider, unregister-provider, select-chain, resolve-plan, inspect-route, bypass, restore, fallback, activate-segment, set-stage-bypass, set-stage-parameter, record-bridge-hit | chain.resolve, chain.inspect, segment.activate, stage.set-bypass, stage.set-parameter, route.bypass, route.restore | Core owns provider selection, route state, chain-plan schema validation, fallback accounting, and diagnostics. Providers propose opaque NAM/IR/VST/utility chain plans; trusted desktop/native code validates and loads processors. Chain selection and route bypass/restore require explicit user action or restored selection. Diagnostics omit raw paths, filenames, URLs, model/IR names, native preset JSON, VST state blobs, handles, callbacks, DOM nodes, audio buffers, samples, and waveforms. |
|
||||
|
||||
| visualization | provider-coordinator | safe | inspect, list-providers, select-renderer, clear-renderer | renderer.create, renderer.destroy | Highway renderer provider registry, picker-delegated selection, auto-match attribution, and failure fallback. `renderer.create` maps to the legacy `window.slopsmithViz_*` factory `init(canvas, ctx)` call; `renderer.destroy` maps to the factory `destroy()` teardown. Legacy `type: "visualization"` manifests and `window.slopsmithViz_*` globals are accounted compatibility shims. Diagnostics carry provider ids/labels, selection source, last auto-match outcome, and last failure — no song filenames, titles, or arrangement names. |
|
||||
| visualization | provider-coordinator | safe | inspect, list-providers, select-renderer, clear-renderer | renderer.create, renderer.destroy | Highway renderer provider registry, picker-delegated selection, auto-match attribution, and failure fallback. `renderer.create` maps to the legacy `window.feedBackViz_*` factory `init(canvas, ctx)` call; `renderer.destroy` maps to the factory `destroy()` teardown. Legacy `type: "visualization"` manifests and `window.feedBackViz_*` globals are accounted compatibility shims. Diagnostics carry provider ids/labels, selection source, last auto-match outcome, and last failure — no song filenames, titles, or arrangement names. |
|
||||
|
||||
| note-detection | provider-coordinator | sensitive | inspect, register-provider, unregister-provider, open-binding, close-binding, set-target, clear-target | pitch.estimate, verify.target | Detection-binding control plane (spec 009): providers (midi/engine/js) serve primitives; each requester binds its own redacted tuning context; consumers own judgment, hit/miss flow as observability events. Legacy `highway.setNoteStateProvider` is an accounted shim. Diagnostics carry provider/binding summaries and bounded outcomes — no raw audio, sample data, device labels, or song identity. |
|
||||
|
||||
@@ -43,6 +43,6 @@ These domains are expected future capability contracts, not current runtime grap
|
||||
| midi-control | multi-provider | sensitive | list-mappings, get-mapping, set-mapping, delete-mapping, activate-mapping, inspect | Mappings ONLY — CC/pitchbend/note → semantic action routing (spec 013). Device discovery/selection/open is NOT this domain's job: it consumes the delivered `midi-input` domain for device access. Needs a concrete mapping consumer (the MIDI control plugin / drums learn-mode) + redacted diagnostics (no raw MIDI streams) before promotion. |
|
||||
| tempo-clock | multi-provider | safe | register, inspect | Needs a concrete provider and consumer workflow. |
|
||||
|
||||
Planned domains should also stay out of the runtime graph until Slopsmith ships the corresponding user-facing workflows.
|
||||
Planned domains should also stay out of the runtime graph until FeedBack ships the corresponding user-facing workflows.
|
||||
|
||||
When promoting a planned domain, use [capability-review-preflight.md](capability-review-preflight.md) before opening the PR. The preflight captures recurring review requirements for identity, redaction, outcome propagation, diagnostics freshness, schema consistency, and teardown.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Slopsmith Diagnostics Bundle — Format Specification
|
||||
# FeedBack Diagnostics Bundle — Format Specification
|
||||
|
||||
This document is the authoritative reference for the `slopsmith-diag-*.zip`
|
||||
file produced by Settings → Export Diagnostics (slopsmith#166).
|
||||
This document is the authoritative reference for the `feedBack-diag-*.zip`
|
||||
file produced by Settings → Export Diagnostics (feedBack#166).
|
||||
|
||||
The bundle is consumed by humans (maintainers reading bug reports) **and**
|
||||
AI agents (auto-triage, code-aware assistants). Every JSON file inside
|
||||
@@ -15,17 +15,17 @@ version without guessing.
|
||||
A diagnostic bundle is a plain ZIP archive. The default filename is:
|
||||
|
||||
```
|
||||
slopsmith-diag-<slopsmith-version>-<YYYYMMDD-HHMMSS>.zip
|
||||
feedBack-diag-<feedBack-version>-<YYYYMMDD-HHMMSS>.zip
|
||||
```
|
||||
|
||||
Top-level layout:
|
||||
|
||||
```
|
||||
slopsmith-diag-0.2.4-20260503-143022.zip
|
||||
feedBack-diag-0.2.4-20260503-143022.zip
|
||||
├── manifest.json AI-friendly index, schema 1
|
||||
├── README.txt Human-friendly: what's in here, how to read
|
||||
├── system/
|
||||
│ ├── version.json slopsmith + python + OS
|
||||
│ ├── version.json feedBack + python + OS
|
||||
│ ├── env.json allowlisted env vars only (no secrets)
|
||||
│ ├── hardware.json backend hardware (container-limited if Docker)
|
||||
│ └── plugins.json loaded + orphan plugins, with git info
|
||||
@@ -53,7 +53,7 @@ logs, console, plugins). Missing sections are not represented in
|
||||
{
|
||||
"schema": 1, // bundle schema; bump = breaking change
|
||||
"exported_at": "2026-05-03T14:30:22Z",
|
||||
"slopsmith_version": "0.2.4",
|
||||
"feedBack_version": "0.2.4",
|
||||
"runtime": "docker", // "docker" | "electron" | "bare"
|
||||
"redacted": true, // were redactions applied?
|
||||
"files": [
|
||||
@@ -94,7 +94,7 @@ Field semantics:
|
||||
```jsonc
|
||||
{
|
||||
"schema": "system.version.v1",
|
||||
"slopsmith_version": "0.2.4",
|
||||
"feedBack_version": "0.2.4",
|
||||
"python": { "version": "3.12.4", "implementation": "CPython", "executable": "/usr/bin/python" },
|
||||
"os": { "system": "Linux", "release": "6.5.0", "machine": "x86_64" },
|
||||
"exported_at": "2026-05-03T14:30:22Z"
|
||||
@@ -109,13 +109,13 @@ Field semantics:
|
||||
"vars": {
|
||||
"LOG_LEVEL": "INFO",
|
||||
"LOG_FORMAT": "json",
|
||||
"SLOPSMITH_RUNTIME": "electron"
|
||||
"FEEDBACK_RUNTIME": "electron"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Allowlisted env var keys only (see `ENV_ALLOWLIST` in `lib/diagnostics_bundle.py`):
|
||||
`LOG_LEVEL`, `LOG_FORMAT`, `LOG_FILE`, `SLOPSMITH_RUNTIME`, `PORT`, `HOST`,
|
||||
`LOG_LEVEL`, `LOG_FORMAT`, `LOG_FILE`, `FEEDBACK_RUNTIME`, `PORT`, `HOST`,
|
||||
`TZ`, `PYTHONUNBUFFERED`, `DEMUCS_SERVER_URL`. New entries require an
|
||||
allowlist edit; secrets must never be added.
|
||||
|
||||
@@ -177,7 +177,7 @@ entry explaining why.
|
||||
"capability_validation_warnings": [],
|
||||
"capability_unsupported_versions": [],
|
||||
"compatibility_shims": [],
|
||||
"git": { "sha": "abc123d", "remote": "https://github.com/topkoa/slopsmith-plugin-stems.git" }
|
||||
"git": { "sha": "abc123d", "remote": "https://github.com/topkoa/feedBack-plugin-stems.git" }
|
||||
}
|
||||
],
|
||||
"orphans": [
|
||||
@@ -187,7 +187,7 @@ entry explaining why.
|
||||
"version": "0.1.0",
|
||||
"loaded": false,
|
||||
"dir": "broken",
|
||||
"path": "/home/user/.config/slopsmith/plugins/broken"
|
||||
"path": "/home/user/.config/feedBack/plugins/broken"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -223,7 +223,7 @@ appear in `capability_unsupported_versions` and should be treated as
|
||||
non-executable runtime intent.
|
||||
|
||||
Client-side capability snapshots contributed under `plugins/capabilities/client.json`
|
||||
use schema `slopsmith.capabilities.diagnostics.v1`. They include current
|
||||
use schema `feedBack.capabilities.diagnostics.v1`. They include current
|
||||
pipelines, participants, conflicts, missing providers, user overrides, active
|
||||
or orphaned claims, claim lifecycle records, compatibility shim hit counts,
|
||||
unsupported-version reports, and recent decisions. The runtime caps this
|
||||
@@ -235,7 +235,7 @@ current graph state.
|
||||
```jsonc
|
||||
{
|
||||
"schema": "logs.server.v1",
|
||||
"log_file": "/data/log/slopsmith.log",
|
||||
"log_file": "/data/log/feedBack.log",
|
||||
"exists": true,
|
||||
"size_bytes": 8388608,
|
||||
"tail_bytes": 5242880,
|
||||
@@ -341,7 +341,7 @@ serialized as `"[circular]"`.
|
||||
`runtime.kind` rules:
|
||||
|
||||
- `"electron"` if `navigator.userAgent` contains `Electron/`. Versions
|
||||
populated when the desktop launcher exposes `window.slopsmithElectron`
|
||||
populated when the desktop launcher exposes `window.feedBackElectron`
|
||||
via a preload `contextBridge`.
|
||||
- `"browser"` otherwise.
|
||||
|
||||
@@ -367,7 +367,7 @@ typically prefix their keys with their `plugin_id`.
|
||||
{
|
||||
"schema": "client.ua.v1",
|
||||
"userAgent": "...",
|
||||
"url": "https://slopsmith.local/",
|
||||
"url": "https://feedBack.local/",
|
||||
"screen": { ... }
|
||||
}
|
||||
```
|
||||
@@ -406,10 +406,10 @@ dispatch by plugin schema.
|
||||
|
||||
Detection precedence (backend):
|
||||
|
||||
1. `SLOPSMITH_RUNTIME` env var (`"electron"`/`"docker"`/`"bare"`)
|
||||
1. `FEEDBACK_RUNTIME` env var (`"electron"`/`"docker"`/`"bare"`)
|
||||
2. `/.dockerenv` exists OR `/proc/1/cgroup` mentions `docker`/
|
||||
`containerd`/`kubepods` → `docker`
|
||||
3. Parent process name matches `electron` or `Slopsmith` → `electron`
|
||||
3. Parent process name matches `electron` or `FeedBack` → `electron`
|
||||
4. Default: `bare`
|
||||
|
||||
Detection (frontend): `Electron/` in user agent → `electron`, else
|
||||
@@ -430,7 +430,7 @@ between bundles):
|
||||
|--------------------|-----------------------------------------------------|
|
||||
| `<DLC_DIR>` | configured DLC root path |
|
||||
| `<HOME>` | user's home directory |
|
||||
| `<CONFIG_DIR>` | slopsmith config directory |
|
||||
| `<CONFIG_DIR>` | feedBack config directory |
|
||||
| `<song:HASH8>` | song filename / basename (8-char salted SHA-256) |
|
||||
| `<ip:HASH6>` | IPv4 / IPv6 address |
|
||||
| `<redacted>` | bearer token, `key=`/`token=`/`api_key=` query strings |
|
||||
@@ -508,7 +508,7 @@ machine.
|
||||
```
|
||||
|
||||
Frontend plugins push diagnostics by calling
|
||||
`window.slopsmith.diagnostics.contribute(plugin_id, payload)` before the
|
||||
`window.feedBack.diagnostics.contribute(plugin_id, payload)` before the
|
||||
user clicks Export. The payload is written to `plugins/<id>/client.json`
|
||||
(gated on the same "Plugin diagnostics" toggle as backend plugin files).
|
||||
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
# Slopsmith diagnostic sloppaks
|
||||
# FeedBack diagnostic sloppaks
|
||||
|
||||
Generated, non-copyrighted mini-songs for technique-assessment style
|
||||
checks. Report-only — they do not change gameplay settings or detection
|
||||
@@ -6,7 +6,7 @@ thresholds.
|
||||
|
||||
## Basic Guitar (POC)
|
||||
|
||||
**Artifact:** `slopsmith-diagnostic-basic-guitar.sloppak`
|
||||
**Artifact:** `feedBack-diagnostic-basic-guitar.sloppak`
|
||||
|
||||
**Contents (~55 s):**
|
||||
|
||||
@@ -23,7 +23,7 @@ for future Technique Assessment integration).
|
||||
|
||||
## Rebuild
|
||||
|
||||
From the slopsmith repo root (requires `ffmpeg`; the slopsmith Docker image
|
||||
From the feedBack repo root (requires `ffmpeg`; the feedBack Docker image
|
||||
has `libvorbis`, Homebrew ffmpeg may use the built-in `vorbis` encoder):
|
||||
|
||||
```bash
|
||||
@@ -36,14 +36,14 @@ On library scan startup (and periodic rescans), the server copies bundled
|
||||
diagnostic sloppaks into the user DLC folder when missing or when the
|
||||
bundled source is newer:
|
||||
|
||||
`DLC_DIR/diagnostics-builtin/slopsmith-diagnostic-basic-guitar.sloppak`
|
||||
`DLC_DIR/diagnostics-builtin/feedBack-diagnostic-basic-guitar.sloppak`
|
||||
|
||||
Source: `docs/diagnostics/slopsmith-diagnostic-basic-guitar.sloppak` (next to
|
||||
Source: `docs/diagnostics/feedBack-diagnostic-basic-guitar.sloppak` (next to
|
||||
`server.py` in dev; must be included in the desktop bundle — see
|
||||
`slopsmith-desktop/scripts/bundle-slopsmith.sh`).
|
||||
`feedBack-desktop/scripts/bundle-feedBack.sh`).
|
||||
|
||||
Unlike `tutorials-builtin/`, `diagnostics-builtin/` **is** included in the
|
||||
library scan. Tracks appear under **Slopsmith** /
|
||||
library scan. Tracks appear under **FeedBack** /
|
||||
**Technique Assessment Diagnostics**.
|
||||
|
||||
Existing destination files are not overwritten unless the bundled source
|
||||
@@ -55,10 +55,10 @@ are never touched.
|
||||
Normally seeding is automatic once a DLC folder is configured. To test a
|
||||
custom copy or an unreleased build:
|
||||
|
||||
1. Copy `slopsmith-diagnostic-basic-guitar.sloppak` into your Slopsmith
|
||||
1. Copy `feedBack-diagnostic-basic-guitar.sloppak` into your FeedBack
|
||||
DLC folder (e.g. `diagnostics-test/` or any scanned path).
|
||||
2. Restart Slopsmith or trigger a library rescan if the song does not appear.
|
||||
3. Load **Slopsmith Diagnostic — Basic Guitar**.
|
||||
2. Restart FeedBack or trigger a library rescan if the song does not appear.
|
||||
3. Load **FeedBack Diagnostic — Basic Guitar**.
|
||||
4. Play the **Diagnostic Guitar** arrangement.
|
||||
5. Confirm the 3D highway shows open notes and power-chord gems.
|
||||
6. Turn **Detect** on — note_detect should push the chart to the desktop
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
"""Build the Slopsmith Diagnostic — Basic Guitar sloppak (POC).
|
||||
"""Build the FeedBack Diagnostic — Basic Guitar sloppak (POC).
|
||||
|
||||
A short, generated, non-copyrighted mini-song for technique-assessment
|
||||
style checks: open strings, one fretted note, and repeated E5 power chords.
|
||||
Click-track backing only — no external audio.
|
||||
|
||||
Run from the slopsmith repo root:
|
||||
Run from the feedBack repo root:
|
||||
|
||||
python3 docs/diagnostics/build_diagnostic_basic_guitar.py
|
||||
|
||||
Output (zip archive):
|
||||
|
||||
docs/diagnostics/slopsmith-diagnostic-basic-guitar.sloppak
|
||||
docs/diagnostics/feedBack-diagnostic-basic-guitar.sloppak
|
||||
|
||||
Pattern matches docs/benchmarks/note_detect_v1/build_benchmark.py.
|
||||
"""
|
||||
@@ -289,8 +289,8 @@ def build_chart():
|
||||
}
|
||||
|
||||
manifest = {
|
||||
'title': 'Slopsmith Diagnostic — Basic Guitar',
|
||||
'artist': 'Slopsmith',
|
||||
'title': 'FeedBack Diagnostic — Basic Guitar',
|
||||
'artist': 'FeedBack',
|
||||
'album': 'Technique Assessment Diagnostics',
|
||||
'year': 2026,
|
||||
'duration': round(end_t, 3),
|
||||
@@ -405,7 +405,7 @@ def build(output_zip: Path) -> dict:
|
||||
|
||||
|
||||
def _diagnostic_readme(duration_s: float) -> str:
|
||||
return f"""# Slopsmith Diagnostic — Basic Guitar
|
||||
return f"""# FeedBack Diagnostic — Basic Guitar
|
||||
|
||||
Short generated diagnostic track for technique-assessment style checks.
|
||||
Non-copyrighted click-track backing only.
|
||||
@@ -422,7 +422,7 @@ Built by docs/diagnostics/build_diagnostic_basic_guitar.py
|
||||
|
||||
def main():
|
||||
repo_root = Path(__file__).resolve().parents[2]
|
||||
default_out = Path(__file__).resolve().parent / 'slopsmith-diagnostic-basic-guitar.sloppak'
|
||||
default_out = Path(__file__).resolve().parent / 'feedBack-diagnostic-basic-guitar.sloppak'
|
||||
out = Path(sys.argv[1]) if len(sys.argv) > 1 else default_out
|
||||
if not out.is_absolute():
|
||||
out = repo_root / out
|
||||
|
||||
+11
-11
@@ -13,7 +13,7 @@ Detection quality varies by guitar pickup, audio interface, monitor latency, the
|
||||
|
||||
## The benchmark sloppak
|
||||
|
||||
The distributable sloppak ships in-tree at [docs/benchmarks/note_detect_v1/note_detect_benchmark_v1.sloppak](benchmarks/note_detect_v1/note_detect_benchmark_v1.sloppak) — drop it directly in your library folder (e.g. `<your-library>/sloppak/`) and it shows up in the library. The file is a zip under the hood but slopsmith's loader (`is_sloppak`) keys off the `.sloppak` suffix, so don't rename. After playing it once it ends up extracted under `static/sloppak_cache/note_detect_benchmark_v1.sloppak/`, which is where the harness reads its `arrangements/lead.json` from. 90 BPM, 8 numbered sections, ~2:20 total:
|
||||
The distributable sloppak ships in-tree at [docs/benchmarks/note_detect_v1/note_detect_benchmark_v1.sloppak](benchmarks/note_detect_v1/note_detect_benchmark_v1.sloppak) — drop it directly in your library folder (e.g. `<your-library>/sloppak/`) and it shows up in the library. The file is a zip under the hood but feedBack's loader (`is_sloppak`) keys off the `.sloppak` suffix, so don't rename. After playing it once it ends up extracted under `static/sloppak_cache/note_detect_benchmark_v1.sloppak/`, which is where the harness reads its `arrangements/lead.json` from. 90 BPM, 8 numbered sections, ~2:20 total:
|
||||
|
||||
| Section | Notes | Isolates |
|
||||
|---|---|---|
|
||||
@@ -28,10 +28,10 @@ The distributable sloppak ships in-tree at [docs/benchmarks/note_detect_v1/note_
|
||||
|
||||
Every chart note has `sus > 0` — so anything you tune against this benchmark exercises the sustain path, not staccato detection. (If we add a staccato section later, the cleanest split is by section name; don't categorize by `sus` value on the event log — see the "Common pitfalls" section.)
|
||||
|
||||
To rebuild after edits to the exercise list, follow the docstring at the top of `build_benchmark.py`. The script writes both an unzipped directory (`.sloppak/`) and a zipped archive (`.sloppak.zip`). The slopsmith library scanner (`lib/sloppak.py::is_sloppak()`) matches on the `.sloppak` suffix, **not** on `.sloppak.zip` — the directory form is usable as-is, but the zip output needs its suffix swapped before it'll be discovered. After regenerating, copy the zip output to the tracked path with the `.sloppak` suffix so it stays a drop-in install. Run from the slopsmith repo root so the relative paths resolve:
|
||||
To rebuild after edits to the exercise list, follow the docstring at the top of `build_benchmark.py`. The script writes both an unzipped directory (`.sloppak/`) and a zipped archive (`.sloppak.zip`). The feedBack library scanner (`lib/sloppak.py::is_sloppak()`) matches on the `.sloppak` suffix, **not** on `.sloppak.zip` — the directory form is usable as-is, but the zip output needs its suffix swapped before it'll be discovered. After regenerating, copy the zip output to the tracked path with the `.sloppak` suffix so it stays a drop-in install. Run from the feedBack repo root so the relative paths resolve:
|
||||
|
||||
```bash
|
||||
# From the slopsmith repo root.
|
||||
# From the feedBack repo root.
|
||||
cp static/sloppak_cache/note_detect_benchmark_v1.sloppak.zip \
|
||||
docs/benchmarks/note_detect_v1/note_detect_benchmark_v1.sloppak
|
||||
```
|
||||
@@ -46,7 +46,7 @@ The typical cycle for one tuning hypothesis:
|
||||
2. **Arm a recording** from the gear popover next to the Detect button on the player. Arm before pressing Play.
|
||||
3. **Play through the benchmark** (or any song) at **1.0× playback speed**. Half-speed playback breaks audio↔chart alignment and produces all-miss garbage — see Pitfalls.
|
||||
4. **Auto-save fires on song end.** The WAV lands in `static/note_detect_recordings/note_detect_<slug>_<timestamp>.wav` (bind-mounted, so it's reachable from the host without a copy step).
|
||||
5. **Run the headless harness** with a known config. Paths below assume the note_detect plugin is cloned into `plugins/note_detect/` (see the slopsmith README for the plugin-install flow — note_detect ships as a separate repo):
|
||||
5. **Run the headless harness** with a known config. Paths below assume the note_detect plugin is cloned into `plugins/note_detect/` (see the feedBack README for the plugin-install flow — note_detect ships as a separate repo):
|
||||
```bash
|
||||
node plugins/note_detect/tools/harness.js \
|
||||
--audio static/note_detect_recordings/note_detect_<…>.wav \
|
||||
@@ -162,7 +162,7 @@ The same workflow works on any tuning change — A/V offset sweep, frame-size sw
|
||||
|
||||
### "Did my detector change improve things?" — ad hoc
|
||||
|
||||
Same recording, same chart, two harness runs. Recipe assumes you're at the slopsmith repo root *and* that the Note Detection plugin is cloned at `plugins/note_detect/` per the README. The detector source lives in that nested plugin repo, which slopsmith's `.gitignore` excludes via `plugins/*/`, so the stash dance has to run **inside** the plugin repo — `git stash` from the slopsmith root would either bail out or, worse, stash unrelated slopsmith edits.
|
||||
Same recording, same chart, two harness runs. Recipe assumes you're at the feedBack repo root *and* that the Note Detection plugin is cloned at `plugins/note_detect/` per the README. The detector source lives in that nested plugin repo, which feedBack's `.gitignore` excludes via `plugins/*/`, so the stash dance has to run **inside** the plugin repo — `git stash` from the feedBack root would either bail out or, worse, stash unrelated feedBack edits.
|
||||
|
||||
The stash dance below uses **`git stash push -u -m "..."`** to give the stash a known name *and* include untracked files. `-u` matters: if your detector change added a new module or fixture, an untracked-file-blind stash would leave it on disk during the "before" run and contaminate the baseline. The script then asserts a stash was actually created before popping (so a clean worktree doesn't silently pop someone else's WIP), wraps each step in **`set -euo pipefail`** so a failed `git stash pop` (e.g., conflict) aborts before the "after" harness records an invalid result, and uses `trap` to surface any failure with a clear message.
|
||||
|
||||
@@ -172,7 +172,7 @@ PLUGIN_DIR=plugins/note_detect
|
||||
HARNESS=$PLUGIN_DIR/tools/harness.js
|
||||
STASH_MSG="harness-before-$$"
|
||||
trap 'echo "harness recipe aborted — stash may still be in $PLUGIN_DIR (\"git -C $PLUGIN_DIR stash list\")" >&2' ERR
|
||||
# Stash the detector edits inside the plugin repo, not the slopsmith root.
|
||||
# Stash the detector edits inside the plugin repo, not the feedBack root.
|
||||
# -u also stashes untracked files (new modules, fixtures) so they don't
|
||||
# leak into the "before" baseline. `|| true` only swallows the
|
||||
# clean-worktree case, which the next line catches explicitly.
|
||||
@@ -223,9 +223,9 @@ Find the note's `t` in the chart, then grep the event log for entries near that
|
||||
|
||||
The Note Detection plugin lives in its own repository — these links go to the canonical source at github.com. If you've cloned the plugin into a local `plugins/note_detect/` next to this repo, the same files are at the equivalent path on disk.
|
||||
|
||||
- Plugin source: [`screen.js`](https://github.com/got-feedback/feedback-plugin-notedetect/blob/main/screen.js) — `matchNotes`, `checkMisses`, `_diagTimingErrors` / `_diagTimingErrorsHits`, `getDiagnostic`.
|
||||
- Routes: [`routes.py`](https://github.com/got-feedback/feedback-plugin-notedetect/blob/main/routes.py) — the `/api/plugins/note_detect/recording` and `/api/plugins/note_detect/live-judgment` endpoints.
|
||||
- Harness: [`tools/harness.js`](https://github.com/got-feedback/feedback-plugin-notedetect/blob/main/tools/harness.js).
|
||||
- Regression driver: [`tools/regression.js`](https://github.com/got-feedback/feedback-plugin-notedetect/blob/main/tools/regression.js).
|
||||
- Plugin source: [`screen.js`](https://github.com/got-feedback/feedBack-plugin-notedetect/blob/main/screen.js) — `matchNotes`, `checkMisses`, `_diagTimingErrors` / `_diagTimingErrorsHits`, `getDiagnostic`.
|
||||
- Routes: [`routes.py`](https://github.com/got-feedback/feedBack-plugin-notedetect/blob/main/routes.py) — the `/api/plugins/note_detect/recording` and `/api/plugins/note_detect/live-judgment` endpoints.
|
||||
- Harness: [`tools/harness.js`](https://github.com/got-feedback/feedBack-plugin-notedetect/blob/main/tools/harness.js).
|
||||
- Regression driver: [`tools/regression.js`](https://github.com/got-feedback/feedBack-plugin-notedetect/blob/main/tools/regression.js).
|
||||
- Benchmark builder: [docs/benchmarks/note_detect_v1/build_benchmark.py](benchmarks/note_detect_v1/build_benchmark.py).
|
||||
- Settings UI: [`settings.html`](https://github.com/got-feedback/feedback-plugin-notedetect/blob/main/settings.html) — A/V auto-calibrate panel, tuning-mode toggle, diagnostic block.
|
||||
- Settings UI: [`settings.html`](https://github.com/got-feedback/feedBack-plugin-notedetect/blob/main/settings.html) — A/V auto-calibrate panel, tuning-mode toggle, diagnostic block.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Plugin Capability Inventory
|
||||
|
||||
This report inventories the currently included plugins staged in `plugins/` and maps their observed behavior to Slopsmith capability domains. It is intended to inform the capability roadmap and the next migration specs now that PR1, the audio graph/session slice, playback, and audio-effects are active capability surfaces.
|
||||
This report inventories the currently included plugins staged in `plugins/` and maps their observed behavior to FeedBack capability domains. It is intended to inform the capability roadmap and the next migration specs now that PR1, the audio graph/session slice, playback, and audio-effects are active capability surfaces.
|
||||
|
||||
## Scope And Method
|
||||
|
||||
@@ -8,7 +8,7 @@ This report inventories the currently included plugins staged in `plugins/` and
|
||||
- Verification pass: the original bundled-plugin scan found 25 plugins with backend `routes.py` and 14 plugins with `settings.html`. First-party plugin repos outside `plugins/` were checked separately from their current manifests and handoff docs.
|
||||
- Most bundled plugin entries below are still inferred/recommended declarations. Current first-party manifests now declare active capability intent for `diagnostics`, `pipeline`, `library`, `audio-mix`, `audio-input`, `audio-monitoring`, `stems`, `playback`, `audio-effects`, `jobs`, and privileged capability inventory surfaces where their repos have already migrated.
|
||||
- Manifest fields such as `nav`, `screen`, `settings`, `routes`, and `type: "visualization"` were treated as high-confidence evidence.
|
||||
- Code patterns such as `window.slopsmithViz_*`, `window.playSong` wrappers, `window.showScreen` wrappers, `window.registerShortcut`, `window.slopsmithTour.register`, `window.slopsmith.audio.registerFader`, `highway.setNoteStateProvider`, and route/WebSocket handlers were treated as behavior evidence.
|
||||
- Code patterns such as `window.feedBackViz_*`, `window.playSong` wrappers, `window.showScreen` wrappers, `window.registerShortcut`, `window.feedBackTour.register`, `window.feedBack.audio.registerFader`, `highway.setNoteStateProvider`, and route/WebSocket handlers were treated as behavior evidence.
|
||||
|
||||
## Roadmap Baseline
|
||||
|
||||
@@ -231,11 +231,11 @@ For active domains, command and operation names should follow [capability-domain
|
||||
|
||||
## Highway String Colors (data-plane API)
|
||||
|
||||
User-customizable per-string highway colors (the "Highway String Colors" setting in the 3D Highway plugin's panel) are **not** a capability domain. Consistent with `capability-domains.md` keeping highway-rendering and `visualization` surfaces off the capability graph until a dedicated render-facade slice lands, they are exposed as a synchronous **data-plane** API on `window.slopsmith.highwayColors` plus a change event. Visualization/overlay plugins (custom highways, minigames, fretboard widgets) should read colors from here so their gems/strings match the user's theme.
|
||||
User-customizable per-string highway colors (the "Highway String Colors" setting in the 3D Highway plugin's panel) are **not** a capability domain. Consistent with `capability-domains.md` keeping highway-rendering and `visualization` surfaces off the capability graph until a dedicated render-facade slice lands, they are exposed as a synchronous **data-plane** API on `window.feedBack.highwayColors` plus a change event. Visualization/overlay plugins (custom highways, minigames, fretboard widgets) should read colors from here so their gems/strings match the user's theme.
|
||||
|
||||
Colors are keyed by **named string slot**, not raw index, so a string keeps its color across arrangements (Low E stays Low E's color on a 6-string guitar, 4-string bass, or 7/8-string, where the extra low strings use the `low7`/`low8` slots). Slots: `highE`, `B`, `G`, `D`, `A`, `lowE`, `low7` (7-string Low B), `low8` (8-string Low F#).
|
||||
|
||||
`window.slopsmith.highwayColors` (`version: 1`):
|
||||
`window.feedBack.highwayColors` (`version: 1`):
|
||||
|
||||
| Member | Returns | Purpose |
|
||||
|--------|---------|---------|
|
||||
@@ -250,7 +250,7 @@ Colors are keyed by **named string slot**, not raw index, so a string keeps its
|
||||
| `encodeShare(name, map)` / `decodeShare(code)` | `string` / `{name,colors}` | The `SLOPHWY2.` copy/paste share format. |
|
||||
| `onChange(fn)` / `offChange(fn)` | unsubscribe fn | `fn(resolvedMap)` fires on any color change (also on song load when the slot→index mapping shifts). |
|
||||
|
||||
The underlying change event is `window.slopsmith.emit('highway:stringColors', …)`; `onChange` wraps it and hands back the resolved map. The raw `window.highway.getStringColors()` data-plane accessor (per-index) remains available for renderers that only need the current applied array. When a `visualization` capability slice eventually lands, this facade is the natural thing to fold into it.
|
||||
The underlying change event is `window.feedBack.emit('highway:stringColors', …)`; `onChange` wraps it and hands back the resolved map. The raw `window.highway.getStringColors()` data-plane accessor (per-index) remains available for renderers that only need the current applied array. When a `visualization` capability slice eventually lands, this facade is the natural thing to fold into it.
|
||||
|
||||
## Validation Notes
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://slopsmith.local/contracts/plugin-manifest-capabilities.schema.json",
|
||||
"title": "Slopsmith Plugin Manifest Capability Contract",
|
||||
"$id": "https://feedBack.local/contracts/plugin-manifest-capabilities.schema.json",
|
||||
"title": "FeedBack Plugin Manifest Capability Contract",
|
||||
"type": "object",
|
||||
"required": ["id", "name"],
|
||||
"properties": {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Plugin styling — the `styles` capability
|
||||
|
||||
> Building for the redesigned **v3 UI** (`SLOPSMITH_UI=v3` / `/v3`)? v3 uses `fb-*`
|
||||
> Building for the redesigned **v3 UI** (`FEEDBACK_UI=v3` / `/v3`)? v3 uses `fb-*`
|
||||
> design tokens and a restructured player chrome with a dedicated plugin-control
|
||||
> slot. See **[plugin-v3-ui.md](plugin-v3-ui.md)** for the player-chrome contract
|
||||
> plugins must follow in v3.
|
||||
|
||||
Slopsmith serves Tailwind as a **prebuilt** stylesheet
|
||||
FeedBack serves Tailwind as a **prebuilt** stylesheet
|
||||
(`static/tailwind.min.css`), never the runtime Play CDN. The CDN's on-the-fly
|
||||
JIT rescanned the DOM on the main thread and dropped ~26% of frames with the 3D
|
||||
highway running (slopsmith-desktop#110). See **constitution Principle II**.
|
||||
highway running (feedBack-desktop#110). See **constitution Principle II**.
|
||||
|
||||
A prebuilt stylesheet only contains the classes the build scanner saw in **core
|
||||
source at core build time**. That has a consequence for plugins:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Building plugins for the v3 UI (fee[dB]ack v0.3.0)
|
||||
|
||||
v0.3.0 ("fee[dB]ack") ships a redesigned UI **behind a flag** — `SLOPSMITH_UI=v3`
|
||||
v0.3.0 ("fee[dB]ack") ships a redesigned UI **behind a flag** — `FEEDBACK_UI=v3`
|
||||
or the `/v3` route. The classic UI (v2) remains the default until 0.3.0 ships, so
|
||||
plugins must work in **both**.
|
||||
|
||||
The good news: v3 **reuses the same engine** as v2 — same `server.py`, `app.js`,
|
||||
`highway.js`, `playSong`, `showScreen`, capability registry, library providers,
|
||||
and the `window.slopsmithViz_<id>` / `setRenderer` visualization contract. So your
|
||||
and the `window.feedBackViz_<id>` / `setRenderer` visualization contract. So your
|
||||
plugin's **backend, capabilities, library providers, `nav`/`screen`, visualization
|
||||
renderers, diagnostics, and settings export all work unchanged in v3.** v3 surfaces
|
||||
your `nav` entry in the new sidebar (via `shell.js` `renderPluginNav`) and your
|
||||
@@ -34,8 +34,8 @@ So the legacy way of injecting a control breaks in v3 two ways:
|
||||
|
||||
The host exposes:
|
||||
|
||||
- `window.slopsmith.uiVersion === 'v3'` — detect v3 (absent / not `'v3'` in v2).
|
||||
- `window.slopsmith.ui.playerControlSlot()` — returns a **stable, always-reachable
|
||||
- `window.feedBack.uiVersion === 'v3'` — detect v3 (absent / not `'v3'` in v2).
|
||||
- `window.feedBack.ui.playerControlSlot()` — returns a **stable, always-reachable
|
||||
container** (the "Plugins" rail popover). In v3, append your control(s) here
|
||||
instead of `#player-controls`.
|
||||
|
||||
@@ -43,9 +43,9 @@ Canonical pattern for any control you inject into the player:
|
||||
|
||||
```js
|
||||
function playerSlot() {
|
||||
return (window.slopsmith && window.slopsmith.uiVersion === 'v3'
|
||||
&& window.slopsmith.ui && typeof window.slopsmith.ui.playerControlSlot === 'function')
|
||||
? window.slopsmith.ui.playerControlSlot() : null;
|
||||
return (window.feedBack && window.feedBack.uiVersion === 'v3'
|
||||
&& window.feedBack.ui && typeof window.feedBack.ui.playerControlSlot === 'function')
|
||||
? window.feedBack.ui.playerControlSlot() : null;
|
||||
}
|
||||
|
||||
function injectMyButton() {
|
||||
@@ -183,7 +183,7 @@ out of the capability graph.
|
||||
- [ ] Backend / capabilities / library provider / `nav` + `screen` /
|
||||
visualization renderer — **no change needed** (they work in v3 as-is).
|
||||
- [ ] If you inject a control into the player: detect v3 and mount into
|
||||
`window.slopsmith.ui.playerControlSlot()`; drop the dead separator /
|
||||
`window.feedBack.ui.playerControlSlot()`; drop the dead separator /
|
||||
`button:last-child` anchor; guard `contains()` against the actual container.
|
||||
- [ ] Dropdowns positioned via `getBoundingClientRect()`, not `#player-controls`.
|
||||
- [ ] `#player` overlays keep `z-index` ≤ the chrome layers (transport/HUD 20,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Debugging Keyboard Shortcuts
|
||||
|
||||
This skill helps you debug keyboard shortcut issues in Slopsmith.
|
||||
This skill helps you debug keyboard shortcut issues in FeedBack.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Start Slopsmith:**
|
||||
1. **Start FeedBack:**
|
||||
```bash
|
||||
cd ~/path/to/slopsmith
|
||||
cd ~/path/to/feedBack
|
||||
LIBRARY_PATH=/path/to/your/library docker compose up -d
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ A `.sloppak` is just a zip of plain files: some YAML, some JSON, some OGG audio,
|
||||
|
||||
This guide walks through the most common edits, aimed at musicians who are comfortable with a text editor and Audacity but don't live on the command line.
|
||||
|
||||
> For the format **schema** (what every field means, how the wire format works, how to extend the format with new data types), see the authoritative [feedpak spec](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md) (the local [sloppak-spec.md](sloppak-spec.md) is now a pointer to it). This document is the **how-do-I-actually-edit-mine** companion.
|
||||
> For the format **schema** (what every field means, how the wire format works, how to extend the format with new data types), see the authoritative [feedpak spec](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md) (the local [sloppak-spec.md](sloppak-spec.md) is now a pointer to it). This document is the **how-do-I-actually-edit-mine** companion.
|
||||
|
||||
---
|
||||
|
||||
@@ -17,27 +17,27 @@ A sloppak exists in two interchangeable forms:
|
||||
| **Directory** | A folder named `something.sloppak/` with the files loose inside | **Authoring** — easy to edit, no zip/unzip cycle |
|
||||
| **Zip** | A `something.sloppak` file (zip with the same files inside) | **Distributing** — single file to share |
|
||||
|
||||
Slopsmith reads both. You can drop either one straight into your DLC folder and it'll show up in the library.
|
||||
FeedBack reads both. You can drop either one straight into your DLC folder and it'll show up in the library.
|
||||
|
||||
### Unzipping for editing
|
||||
|
||||
Slopsmith's converter ships sloppaks in zip form. To edit one, unzip it:
|
||||
FeedBack's converter ships sloppaks in zip form. To edit one, unzip it:
|
||||
|
||||
- **Windows:** rename `mysong.sloppak` → `mysong.zip`, right-click → Extract All. Then rename the resulting folder back to `mysong.sloppak/` (with the trailing slash / folder form). Or use [7-Zip](https://www.7-zip.org/) and unzip without renaming.
|
||||
- **macOS:** rename `.sloppak` → `.zip`, double-click. Or use The Unarchiver.
|
||||
- **Linux:** `unzip mysong.sloppak -d mysong.sloppak/`.
|
||||
|
||||
Once you have the directory form, you can edit any file inside and Slopsmith will pick it up — no re-zipping required for your own use.
|
||||
Once you have the directory form, you can edit any file inside and FeedBack will pick it up — no re-zipping required for your own use.
|
||||
|
||||
### Cache: when changes don't appear
|
||||
|
||||
The first time Slopsmith opens a zip-form sloppak, it extracts a working copy into its config directory's cache: `${CONFIG_DIR}/sloppak_cache/<safe-id>` (in the standard Docker setup that's inside the `slopsmith-config` volume, mounted at `/config` in the container). The `<safe-id>` is the sloppak filename with each path separator (`/` or `\`) replaced by `__` and each space replaced by `_`. So `My-Song.sloppak` stays `My-Song.sloppak`, and `Artist/My Song.sloppak` becomes `Artist__My_Song.sloppak`.
|
||||
The first time FeedBack opens a zip-form sloppak, it extracts a working copy into its config directory's cache: `${CONFIG_DIR}/sloppak_cache/<safe-id>` (in the standard Docker setup that's inside the `feedBack-config` volume, mounted at `/config` in the container). The `<safe-id>` is the sloppak filename with each path separator (`/` or `\`) replaced by `__` and each space replaced by `_`. So `My-Song.sloppak` stays `My-Song.sloppak`, and `Artist/My Song.sloppak` becomes `Artist__My_Song.sloppak`.
|
||||
|
||||
You almost never need to touch this cache directly. If you edit the **original zip** in your DLC folder, Slopsmith re-extracts automatically when the zip's modification time or size changes — just save your edits and reload.
|
||||
You almost never need to touch this cache directly. If you edit the **original zip** in your DLC folder, FeedBack re-extracts automatically when the zip's modification time or size changes — just save your edits and reload.
|
||||
|
||||
If a change still isn't appearing, the simplest reset is to remove the matching cache folder so Slopsmith rebuilds it on the next song load. In a default Docker install that's `docker exec <container> rm -rf /config/sloppak_cache/<safe-id>` (or the equivalent for your setup).
|
||||
If a change still isn't appearing, the simplest reset is to remove the matching cache folder so FeedBack rebuilds it on the next song load. In a default Docker install that's `docker exec <container> rm -rf /config/sloppak_cache/<safe-id>` (or the equivalent for your setup).
|
||||
|
||||
If you'd rather skip the cache layer entirely, **drop the directory form straight into your DLC folder** — Slopsmith uses it in place and there's nothing to invalidate.
|
||||
If you'd rather skip the cache layer entirely, **drop the directory form straight into your DLC folder** — FeedBack uses it in place and there's nothing to invalidate.
|
||||
|
||||
---
|
||||
|
||||
@@ -72,8 +72,8 @@ The use case: the converted rhythm guitar sounds muddy (Demucs has a tough time
|
||||
1. Copy `rhythm_custom.ogg` into the sloppak's `stems/` folder.
|
||||
2. Open `manifest.yaml` in any text editor (Notepad++, VS Code, BBEdit, gedit — all fine; just **don't use Word**).
|
||||
3. Find the `stems:` block. Two things matter here:
|
||||
- **Order:** Slopsmith's base `<audio>` element always plays the **first** stem listed in `stems[]`, regardless of `default:` flags. So if you want your custom stem to be what the player plays out-of-the-box (and what users without the Stems plugin will hear), put it **first**.
|
||||
- **`default:` flags:** consulted by the [Stems plugin](https://github.com/topkoa/slopsmith-plugin-stems) to decide which faders start un-muted. They do **not** affect what the base `<audio>` element plays — that's purely the first-stem rule above.
|
||||
- **Order:** FeedBack's base `<audio>` element always plays the **first** stem listed in `stems[]`, regardless of `default:` flags. So if you want your custom stem to be what the player plays out-of-the-box (and what users without the Stems plugin will hear), put it **first**.
|
||||
- **`default:` flags:** consulted by the [Stems plugin](https://github.com/topkoa/feedBack-plugin-stems) to decide which faders start un-muted. They do **not** affect what the base `<audio>` element plays — that's purely the first-stem rule above.
|
||||
|
||||
Example for a Demucs-split sloppak where you re-recorded the rhythm guitar:
|
||||
|
||||
@@ -110,14 +110,14 @@ The use case: the converted rhythm guitar sounds muddy (Demucs has a tough time
|
||||
|
||||
### Step 5 — Reload and verify
|
||||
|
||||
Reload the song in Slopsmith. The [Stems plugin](https://github.com/topkoa/slopsmith-plugin-stems) will show a fader for `rhythm_custom` next to the others. If you don't see it, check the cache notes in §1.
|
||||
Reload the song in FeedBack. The [Stems plugin](https://github.com/topkoa/feedBack-plugin-stems) will show a fader for `rhythm_custom` next to the others. If you don't see it, check the cache notes in §1.
|
||||
|
||||
### Common gotchas
|
||||
|
||||
- **Sample-rate mismatch** → choppy/pitched-wrong playback. Re-export from Audacity at exactly the rate the other stems use.
|
||||
- **Mono vs stereo mismatch** is fine for playback but levels can feel different — match what the other stems use if you want consistent behavior in the mixer.
|
||||
- **Silence padding at the start** of your recording → your stem will play late. Trim it tight in Audacity before exporting.
|
||||
- **Tabs in `manifest.yaml`** → Slopsmith will refuse to load the song. Use two spaces.
|
||||
- **Tabs in `manifest.yaml`** → FeedBack will refuse to load the song. Use two spaces.
|
||||
|
||||
---
|
||||
|
||||
@@ -242,7 +242,7 @@ For 4-string bass, only indices 0–3 are meaningful; leave 4 and 5 at `0`.
|
||||
|
||||
### What *not* to put in `manifest.yaml`
|
||||
|
||||
Don't add per-machine settings (audio device picks, MIDI port IDs), UI state, or your own play counts. The sloppak holds the song's authored data — anything that varies by user or machine lives in Slopsmith's config dir or the metadata DB. See [feedpak spec §9.5](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md#95-what-does-not-belong-in-a-feedpak) for the full list.
|
||||
Don't add per-machine settings (audio device picks, MIDI port IDs), UI state, or your own play counts. The sloppak holds the song's authored data — anything that varies by user or machine lives in FeedBack's config dir or the metadata DB. See [feedpak spec §9.5](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md#95-what-does-not-belong-in-a-feedpak) for the full list.
|
||||
|
||||
---
|
||||
|
||||
@@ -252,15 +252,15 @@ If you want to share your modified sloppak with someone else, re-zip it:
|
||||
|
||||
1. Open the `mysong.sloppak/` directory.
|
||||
2. Select **everything inside** — `manifest.yaml`, `arrangements/`, `stems/`, `lyrics.json`, `cover.jpg`.
|
||||
3. Zip the **contents**, not the parent folder. (If you zip the folder, the zip will have a top-level `mysong.sloppak/` directory inside, which Slopsmith won't parse — the manifest must be at the zip root.)
|
||||
3. Zip the **contents**, not the parent folder. (If you zip the folder, the zip will have a top-level `mysong.sloppak/` directory inside, which FeedBack won't parse — the manifest must be at the zip root.)
|
||||
4. Rename `mysong.zip` → `mysong.sloppak`.
|
||||
|
||||
For your own use, you can skip this entirely — Slopsmith reads the directory form straight from your DLC folder.
|
||||
For your own use, you can skip this entirely — FeedBack reads the directory form straight from your DLC folder.
|
||||
|
||||
---
|
||||
|
||||
## Out of scope (for now)
|
||||
|
||||
- **Authoring a sloppak from scratch** (no Guitar Pro / MusicXML source file) — that's a developer task. Start at [feedpak spec §8 (Reading and writing)](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md#8-reading-and-writing).
|
||||
- **Editing notes / chords in `arrangements/*.json`** — technically possible but extremely tedious by hand: hundreds of objects with short field names per song. The fields are documented in [feedpak spec §6 (Arrangement JSON)](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md#6-arrangement-json), but for any real chart edit you want the [Arrangement Editor plugin](https://github.com/got-feedback/feedback-plugin-editor).
|
||||
- **Authoring a sloppak from scratch** (no Guitar Pro / MusicXML source file) — that's a developer task. Start at [feedpak spec §8 (Reading and writing)](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md#8-reading-and-writing).
|
||||
- **Editing notes / chords in `arrangements/*.json`** — technically possible but extremely tedious by hand: hundreds of objects with short field names per song. The fields are documented in [feedpak spec §6 (Arrangement JSON)](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md#6-arrangement-json), but for any real chart edit you want the [Arrangement Editor plugin](https://github.com/got-feedback/feedBack-plugin-editor).
|
||||
- **Loudness normalization / advanced stem processing** — out of scope here; standard Audacity or ffmpeg workflows apply to any OGG file before you drop it into `stems/`.
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
The full format specification that used to live here has moved to its own repository and is now
|
||||
the **authoritative, versioned reference**:
|
||||
|
||||
> **📖 https://github.com/got-feedback/feedback-feedpak-spec**
|
||||
> — normative spec ([`spec/feedpak-v1.md`](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md)),
|
||||
> **📖 https://github.com/got-feedback/feedpak-spec**
|
||||
> — normative spec ([`spec/feedpak-v1.md`](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md)),
|
||||
> JSON Schemas, examples, and a reference validator.
|
||||
|
||||
Update bookmarks to point there. This page is a thin pointer kept at the original path so existing
|
||||
@@ -14,7 +14,7 @@ links keep resolving.
|
||||
|
||||
The published format is named **feedpak** (extension `.feedpak`, manifest key `feedpak_version`).
|
||||
This codebase still uses the legacy **sloppak** name internally — `lib/sloppak.py`, the
|
||||
`.sloppak` extension, `SLOPSMITH_*` env vars, etc. **They describe the same on-disk format.** The
|
||||
`.sloppak` extension, `FEEDBACK_*` env vars, etc. **They describe the same on-disk format.** The
|
||||
rename is repo/public-facing only for now (see the top-level workspace `CLAUDE.md`), so when the
|
||||
spec says `feedpak` / `feedpak_version`, the packs this server reads and writes today are the same
|
||||
structure under the `.sloppak` name. The internal rename is a separate, later effort.
|
||||
@@ -45,5 +45,5 @@ concepts to the code that reads and writes them. It is **not** part of the forma
|
||||
> **Note on older section references.** Some inline code comments in this repo cite section
|
||||
> numbers from the previous version of this document (e.g. "sloppak-spec §5.3"). The external spec
|
||||
> renumbered its sections, so those citations are approximate — find the topic by name in the
|
||||
> [feedpak spec](https://github.com/got-feedback/feedback-feedpak-spec/blob/main/spec/feedpak-v1.md)
|
||||
> [feedpak spec](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md)
|
||||
> rather than by the old number.
|
||||
|
||||
Reference in New Issue
Block a user