Commit Graph
23 Commits
Author SHA1 Message Date
5188aab938 feat(config): real config reset/repair + migration framework (drop manual-delete) (#38)
Eliminates the fragile "delete the config folder before upgrading" tester
instruction, which was wrong-by-OS because the userData folder name was
derived inconsistently per platform (fee[dB]ack on macOS, slopsmith-desktop
on Linux/Windows).

A. Deterministic paths + migration framework
- Pin the userData name on every OS via app.setName('feedback-desktop') +
  build.extraMetadata.name; brand (productName 'fee[dB]ack') unchanged.
- One-time userData migration copies a legacy folder into the new one so
  upgraded users don't start fresh (atomic copy-then-rename, fail-soft).
  Runs before the single-instance lock / crashReporter, which would otherwise
  create userData and defeat the "new dir doesn't exist" gate.
- config-migrations.ts: versioned, ordered, idempotent, fail-soft migration
  runner stamped in CONFIG_DIR/config_version.json; logs the active CONFIG_DIR
  at startup (closes the Linux ~/.local/share/slopsmith shared-config gap).

B. In-app "Reset / repair configuration" (Settings panel)
- Granular options: reset app settings & caches, clear plugin state & cached
  Python deps, and full reset with default-OFF opt-ins for installed plugins /
  song library / ML caches.
- config-paths.ts is the single source of truth for per-OS path enumeration;
  the song library, installed plugins and ML caches are structurally confined
  to optInExtras and never wiped by the safe/full categories.
- Reset stops the backend, deletes immediate paths, includes SQLite WAL/SHM
  sidecars + the migration stamp on full reset, and defers Chromium/Crashpad
  state to next launch (consumed before any window reopens it). ML caches honor
  TORCH_HOME/HF_HOME. Empty selection is a no-op (backend left running).
- SECURITY: destructive resets require a native main-process confirmation
  dialog — the renderer bridge is reachable by plugin scripts, so a
  renderer-only confirm is not a sufficient gate.

Tests: node:test suites for path enumeration (per-OS + library/plugins
preserved), migration idempotency/fail-soft, reset delete pipeline guarantees,
userData migration, and deferred-deletion schedule/consume. `npm test` green
(adds a test script). codex review --base origin/main clean.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 22:13:24 +02:00
cc0aceb365 feat(sandbox): native last-chance crash attribution for in-process VST3 faults (#36)
* feat(sandbox): native last-chance crash attribution for in-process VST3 faults (#35)

The vst-crash-guard sentinel only covers the windows it arms around an
in-process load or editor-open. A plugin that creates a top-level window keeps
it for its whole loaded lifetime, and the OS can dispatch to its WndProc at any
time (e.g. WM_ACTIVATEAPP on an alt-tab). A fault there arrives via USER32→
WndProc with no host frame on the stack — outside every armed sentinel window
and uncatchable by the SignalChain guard — so it's never attributed and the app
crash-loops (diagnosed from dmp a06f48e1 / McRocklin Suite; see #35).

Add a process-wide last-chance attributor (Windows): a SetUnhandledException
filter, chained to the previously installed filter (Crashpad), that on a fatal
fault whose faulting instruction lies inside a loaded .vst3 module stamps the
existing crash sentinel with { plugin, op: "native-crash" } and then defers to
the prior filter so the dump is still produced and the process dies normally.
initVstCrashGuard() already promotes a leftover sentinel into the persistent
blocklist, so the next launch routes the offender to the out-of-process sandbox.
This makes the dead-man's-pedal cover ANY fatal in-process VST3 fault, not just
the armed load/editor windows — generalizing beyond the per-vendor pre-seed.

- src/audio/Sandbox/CrashAttribution.{h,cpp}: install/uninstall + the filter.
  SetUnhandledExceptionFilter (last-chance only) avoids first-chance false
  positives and per-exception I/O; the write is allocation-free (stack buffers +
  raw Win32). No-op on non-Windows (POSIX SignalChain guard covers the armed
  path; sandbox is Windows-only today).
- NodeAddon: setVstCrashSentinelPath(path) binding arms it; uninstall on
  shutdown (the addon/filter code may be unloaded).
- vst-crash-guard.ts: export getSentinelPath(); audio-bridge wires it after
  initVstCrashGuard().

Addon builds clean; tsc --noEmit clean; sandbox tests + e2e unaffected. The
Windows filter path needs hands-on validation (confirm the sentinel is written
and Crashpad still dumps under the target Electron/Crashpad version).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* review: fix bundle-path attribution + one-shot gate in crash attributor

Local review of #36 found two correctness bugs:

- Inert on bundle VST3s: GetModuleFileNameW returns the INNER DLL of a Windows
  VST3 bundle (Foo.vst3\Contents\x86_64-win\Foo.vst3), but the blocklist keys on
  the bundle dir (desc.fileOrIdentifier = …\Foo.vst3). The two never matched, so
  a native-written sentinel never routed the offender to the sandbox — defeating
  the fix for bundle plugins. Add truncateToVst3Bundle(): resolve the module
  path to its enclosing .vst3 component in place before writing (single-file
  .vst3 is unchanged). Replaces endsWithVst3IgnoreCase.

- One-shot latch burned by the wrong exception: the g_writing.exchange gate
  wrapped the whole filter evaluation, so the FIRST unhandled exception to reach
  the filter — even a non-VST3 or concurrent benign one — permanently disabled
  attribution for the real plugin fault. Move the latch to gate only the write,
  after a CONFIRMED .vst3 fatal fault; it still serialises concurrent plugin
  faults and guards write re-entrancy.

Also: stop zeroing g_sentinelPathW in uninstall (the g_installed acquire-gate
already disarms the write path; zeroing was the only non-atomic mutation that
could race a faulting thread during teardown), and note the address-based
attribution is a heuristic.

Addon builds clean; tsc clean. Windows filter path still needs hands-on
validation (sentinel written for a bundle + single-file VST3; Crashpad still
dumps).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:03:06 +02:00
7f8975641e fix(sandbox): force PolyChrome DSP plugins out-of-process (in-process WndProc DEP crash) (#34)
* fix(sandbox): force PolyChrome DSP plugins out-of-process (in-process WndProc DEP crash)

A tester crash dump (feedback.exe 0.3.0, Windows) showed an execute-DEP access
violation (0xC0000005) killing the app while McRocklin Suite.vst3 (PolyChrome
DSP) was loaded IN-PROCESS:

  Rax == Rip == McRocklin Suite.vst3 + 0x1D57050   (non-executable module data)
  caller [Rsp] = USER32.dll+0xEF5C
  WndProc(hwnd=0x51CCA, msg=0x1C WM_ACTIVATEAPP, wParam=1, lParam=0x1838)
  crash thread = the addon's background JUCE MessageManager thread (unnamed;
  start frame slopsmith_audio.node), NOT Electron's CrBrowserMain.

PolyChrome creates a top-level window during in-process init on JUCE's
*background* message thread. Its WndProc lands in non-executable memory there, so
when Windows broadcasts WM_ACTIVATEAPP the OS message pump executes it → DEP AV.
The plugin assumes a real host main UI thread (STA/main); the sandbox child
provides exactly that, so routing it out-of-process both isolates the fault and
gives the plugin the environment it needs.

Crucially this crash cannot be caught by the SignalChain in-process fault guard:
it arrives asynchronously via USER32→WndProc with NO host frame on the stack, so
guarding prepareToPlay/processBlock (or even instantiation) never sees it. Under
the current in-process-by-default policy (#24) the only fix is to not host these
plugins in-process. Graphene (same vendor) was already pre-seeded; this extends
the pre-seed to the whole PolyChrome vendor via a path-fragment match so McRocklin
Suite and any other PolyChrome product route to the sandbox too.

- Add kDefaultNeedsSandboxPathFragments (vendor/path match) + the loop in
  shouldSandbox; seed it with "PolyChrome".
- Refresh the stale kDefaultNeedsSandboxFilenames comment (it still claimed
  sandbox-by-default; #24 made the list authoritative again).
- e2e_test: add testShouldSandboxRouting() — pure shouldSandbox assertions
  (PolyChrome→sandbox, clean VST3→in-process, non-VST3→in-process).

Verified: audio addon builds clean; sandbox_e2e_test green (16/16, routing
assertions included).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* review: tighten PolyChrome match + dedupe path + harden routing test

Local high-effort review of the pre-seed fix surfaced four items; addressed:

- False-positive risk (no in-process fallback exists here — loadVstSandboxAware
  hard-fails a force-sandboxed load that can't spawn the child): narrow the
  fragment from the bare brand word "PolyChrome" to the vendor install folder
  "PolyChrome DSP", so an unrelated path (e.g. a username "polychrome") no
  longer forces the sandbox. Still matches McRocklin Suite + Graphene, which
  ship under Common Files/VST3/PolyChrome DSP/.
- Dedupe: getFullPathName() was computed twice (blocklist `canonical` +
  vendor `fullPath`); hoist one `fullPath` above the mutex block and reuse it.
- Test isolation: assert McRocklin Suite (NOT in the filename pre-seed) on both
  Windows- and POSIX-style paths so the case can only pass via the new vendor
  match; drop the redundant Graphene-in-folder line (Graphene already routes via
  the filename list).
- Test specificity + exit-code masking: add a negative proving a bare
  "polychrome" path is NOT sandboxed (guards the tightening), and surface
  routing CHECK failures on the no-args path (return 1, not the usage code 2)
  so a regression isn't masked on a manual/argless run.

Addon builds clean; sandbox_e2e_test 17/17 green (routing included).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:03:02 +02:00
4d19398a50 build: bundle feedback-plugin-virtuoso (replaces slopscale-fork) (#31)
* build: bundle feedback-plugin-virtuoso (replaces slopscale-fork)

The practice plugin relaunched as Virtuoso (id virtuoso) at got-feedback/feedBack-plugin-virtuoso. Repoint the bundle list off the stale feedback-plugin-slopscale-fork snapshot. The clone-dir derivation strips feedback-plugin- -> dir 'virtuoso', matching plugin.json id; default-branch clone = main. Requested by @xasiklas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: tidy bundled-plugins list (review follow-up)

Addresses the two minor notes on this PR:
- Sort virtuoso into its alphabetical slot (after update-manager); it was
  left in the old slopscale-fork position between setlist and song-preview.
- Fix the stale dirname comment: the prefix stripped is "feedback-plugin-",
  not "slopsmith-plugin-" (pre-existing since the rename; the code at the
  ${owner_repo##*/} / #feedback-plugin- step is unchanged).

No functional change — clone order/dirname resolution is unaffected.

Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
2026-06-22 15:07:04 -05:00
b6515a0585 fix(audio): real device names are not labelSafe pseudonyms (#33)
Codex review of #32: the audio-session sanitizer (_safeInputLabel) returns
`labelPseudonym` UN-redacted (it's assumed already safe), so putting a raw OS
device name there leaks PII (e.g. "Byron's AirPods") to diagnostics/consumers
regardless of labelSafe. Put the real name in `label` instead — the field the
sanitizer can redact for suspicious/PII-looking names — and mark labelSafe only
for the generic "Desktop input N" fallback.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 14:05:01 +02:00
f18b0a51fd fix(audio): surface real audio input device names (not "Desktop input N") (#32)
registerAudioSessionInputSources() discarded the real device name (the
forEach arg was `_deviceName`) and labelled every audio-input source with a
generic `Desktop input ${index+1}` pseudonym — so the audio-input picker
showed "Desktop input 1/2/…" instead of the actual device names. The real
names are already available: AudioEngine reads JUCE getDeviceNames(true),
NodeAddon exposes them as typeInfo.inputs, and the renderer already uses
them for setDevice(). Use that name as the source label, falling back to the
generic form only when it's empty.

(Re-applies a fix that previously lived on the dead byrongamatos/slopsmith-
desktop branch and never reached got-feedback/main.)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 13:20:01 +02:00
7b7a5b59da fix(build): strip dangling symlinks so macOS builds aren't "damaged" (#30)
A local macOS tester reported the DMG as "damaged and can't be opened."
Root cause: the bundled tree contained a dangling symlink — rig_builder
ships a build-time link `vst/src/racks/DPF` -> DISTRHO framework that isn't
present at runtime. A broken symlink is harmless on Linux/squashfs (the
AppImage was fine), but on macOS it:
  - breaks codesign — `spctl` reports "a sealed resource is missing or
    invalid", which Gatekeeper surfaces as "damaged"; and
  - breaks `xattr -dr com.apple.quarantine` — it aborts on the dangling
    link, so even the quarantine-removal workaround can't complete.

Strip dangling symlinks from the cloned core+plugins tree after bundling
(safe on every platform — they're broken/unused). Verified on-device:
after removal + ad-hoc re-sign the app verifies clean and launches once
quarantine is cleared.

Also fix build-macos.sh's artifact check, which still globbed the
pre-rebrand `Slopsmith.app` and falsely reported "No artifacts found" for
the now `feedback.app` bundle.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 08:19:59 +02:00
cb1915f745 build: bundle rig_builder by default (#28)
Add got-feedback/rig_builder to the default bundled-plugin manifest so the
Rig Builder (NAM tone builder) ships with every build. The v3 sidebar now
promotes Rig Builder to a dedicated nav entry, so the plugin should be present.

Note: rig_builder is large (~633 MB of NAM models/assets), so this increases
release artifact size accordingly.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 14:49:03 +02:00
17f554c501 fix(build): make the local + CI Linux build work off main (#26)
Three independent gaps currently break a from-scratch Linux build (and CI):

1. .build-config.json is missing `versions.dotnet`, yet both the devcontainer
   Dockerfile (`dotnet-install.sh --channel ${DOTNET_VERSION}`) and the CI
   workflows (`require('./.build-config.json').versions.dotnet` → setup-dotnet
   `${dotnet}.x`) read it. Empty → the image build / setup-dotnet step fails.
   Add `"dotnet": "8.0"` (Velopack's vpk targets .NET 8; "8.0" satisfies both
   `--channel 8.0` and setup-dotnet's `8.0.x`). Keeps .NET available for
   `vpk pack` on tagged release builds.

2. build-linux-docker.sh never forwards GH_CLONE_TOKEN or SLOPSMITH_REF into
   the container, so a local `bash scripts/build-linux-docker.sh` can't clone
   the private got-feedback core/plugins or select a core ref. Pass both
   through (defaulting SLOPSMITH_REF to main).

3. The ffmpeg libvorbis guard pipes `ffmpeg | grep -wq`, which is racy under
   `set -o pipefail`: grep -q closes the pipe on first match, ffmpeg takes
   SIGPIPE (141), pipefail returns 141, and the guard false-fails even though
   libvorbis is present (reproducible on Docker Desktop). Capture the encoder
   list into a variable first, then grep.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 14:32:01 +02:00
7671385ba8 Audio: song loudness normalization, in-process VSTs (perf), and stereo routing (#24)
* audio: flush denormals in the RT path + normalize the backing track

Two realtime-audio fixes (engine only — no change to amp/effect DSP):

1. Denormal flush (FTZ/DAZ). The signal path is full of IIR state (NAM, cab
   IRs, VST amp/EQ/comp chains); after each note that state decays toward zero
   and lands in the denormal range, where each float op is 10-100x slower. That
   produced sporadic CPU spikes -> buffer underruns heard as random "scratches"
   plus frame stutter (worse with larger buffers, independent of song/tone).
   Add a scoped juce::ScopedNoDenormals at the three RT entry points:
     - AudioEngine::audioDeviceIOCallbackWithContext (whole callback)
     - SignalChain::process (the plugin chain)
     - the sandbox worker's plugin processBlock in src/vst-host/main.cpp
       (VST3s run OUT-OF-PROCESS, so the host-side FTZ doesn't reach them)
   Denormals are sub -300 dBFS, so this is inaudible — CPU only, no tone change.

2. Backing-track loudness normalizer (BackingLeveler.h). Brings each song's
   backing to a consistent -12 LUFS so songs don't jump in level, applied in
   renderBackingBlockLocked BEFORE the mixer's backing-volume fader (so the
   fader still attenuates). Short-term BS.1770 K-weighted AGC (slow, no pumping)
   + a -1 dBFS brickwall limiter. RT-safe (no allocation in process()).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio: extend denormal flush to the split-output path + reuse chain MidiBuffer

Opt-1 low-risk RT tidy-ups (no DSP/tone change):
- ScopedNoDenormals in audioOutputCallback (the split-mode output clock that
  renders the backing track + phase-vocoder + leveler) — the primary callback's
  scope doesn't reach this separate output thread, leaving an IIR/decay path
  unprotected (a remaining source of the periodic "scratches").
- SignalChain::process reuses one juce::MidiBuffer across slots instead of
  copy-constructing it per slot per block (avoids RT-thread allocation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio: per-slot pan + parallel branch routing (St-1 stereo, engine side)

Adds pan-only stereo to the signal chain so the node editor can place one amp
left and another right, pan effects, and let stereo plugins pass true L/R.

ProcessorSlot gains two fields:
  - pan    : -1..+1 constant-power, applied to that slot's output (0 = no-op)
  - branch : 0 = trunk (serial), >=1 = a parallel branch id

SignalChain::process keeps a bit-identical serial fast path when no slot has a
branch. When branches exist it runs the trunk-pre slots in place, snapshots that
as the split source, processes each branch on its own pre-allocated scratch
buffer, pans it, sums the branches into a merge bus, then runs any trunk-post
slots on the merged signal. Scratch is sized in prepare() (never on the RT
thread); falls back to serial for a non-stereo / oversized block.

The dual-mono amp output + post-amp pan is what yields "amp A left, amp B right"
without touching NAM or amp DSP. Preset schema emits pan/branch only when
non-default (mono presets unchanged); N-API gains setPan/setBranch and
getChainState/loadPreset round-trip them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio: per-branch source channel (St-2) — feed a split L/R into separate branches

Extends the parallel-branch model so a stereo-out gear (e.g. a stereo delay) can
send its L output to one branch and its R to another. ProcessorSlot gains
branchSrc (0 = both, 1 = L, 2 = R); when seeding a branch from the split source,
L-only / R-only mono-izes that channel into the branch. Read from any slot in the
branch. N-API setBranchSrc + getChainState/preset round-trip it. Default 0 keeps
existing routing identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio-bridge: expose setPan/setBranch/setBranchSrc to the renderer

The engine N-API gained the stereo routing setters (setPan/setBranch/
setBranchSrc) but the main-process IPC handlers + the preload bridge didn't
forward them, so window.slopsmithDesktop.audio.setPan was undefined and the
node editor's stereo controls no-op'd. Wire all three through audio:setPan /
setBranch / setBranchSrc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio: run scanned VSTs in-process + forward params + cut RT stalls

Big CPU/latency win for chains with VST plugins, plus the missing parameter
path. The out-of-process sandbox exists to crash-isolate the SCAN of unknown
plugins; a plugin only reaches a chain after it scanned cleanly, so paying the
per-block IPC cost (N serial round-trips, memcpy, poll waits) for every block
of playback was pure overhead.

- shouldSandbox(): default VST3 playback to IN-PROCESS. The runtime crash
  blocklist + launch sentinel still route a faulting plugin back through the
  sandbox on its next load, so it self-heals; only genuinely crash-prone gear
  keeps paying for isolation. Eliminates the IPC round-trips + the per-load
  subprocess spawn that caused the load-time "scratches".
- SignalChain::clear(): detach slots under a brief lock, destroy them OFF the
  lock. Sandbox teardown is slow; doing it under `lock` starved the RT
  ScopedTryLock and dropped audio blocks on every chain reload.
- AudioChannel::popBlock(): bounded busy-spin on the write index before the
  blocking poll() — a fast plugin's output lands within microseconds, so we
  skip the syscall + doorbell wakeup latency; a slow plugin falls through to the
  efficient wait (correctness + heavy-chain cost unchanged).
- SandboxedProcessor::setSandboxedParameter() + SignalChain::setParameter()
  route param changes to a sandboxed plugin over the control pipe (kSetParameter)
  — the JUCE getParameters() proxy layer isn't wired, so without this a
  sandboxed plugin's knobs/preset never reached it and it played at defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* audio: PR #24 review follow-ups — POSIX fault guard + routing/spin/leveler fixes

Follow-up fixes from review of PR #24.

== POSIX in-process plugin fault guard (the main one) ==
PR #24 makes scanned VSTs run in-process by default. invokePlugin()'s catch(...)
only catches a plugin fault on Windows (where /EHa maps the SEH access violation
to a C++ exception); on macOS/Linux a plugin SIGSEGV during playback took down
the whole app, breaking the fail-soft-audio + cross-platform guarantees.

Add a POSIX fault guard in SignalChain.cpp: install chained SIGSEGV/SIGBUS/
SIGFPE/SIGILL handlers; while a guarded plugin call is live on the current
thread (thread-local, initial-exec TLS so the handler stays async-signal-safe),
siglongjmp() back into invokePlugin() and take the SAME blocklist+leak+survive
path as Windows. Faults outside a guarded call chain to the previously-installed
handler (V8/ASan/default), so real crashes and sanitizers are never masked. The
guard's armed flag is restored on EVERY exit from the guarded region — normal
return, signal-fault longjmp, and a normal C++ exception from the plugin — so a
thread is never left armed with a stale landing pad. Known limit: stack-overflow
faults aren't reliably caught (no sigaltstack on JUCE audio threads).

Comments in SandboxFactory_shared.cpp updated to match the kept in-process
default (the stale 'every VST3 sandboxes' / 'diagnostic tagging only' notes).

== Smaller correctness/quality fixes ==
- SignalChain parallel path: a branch==0 (trunk) slot interleaved inside the
  branch region was run by none of the loops -> silently dropped. Detect the
  region first and fall back to a serial chain (jassertfalse in debug) so no
  slot is lost if the node-editor contiguity invariant breaks.
- AudioChannel pop busy-spin: add a cpuRelax() (_mm_pause / arm yield) hint.
- BackingLeveler: reset AGC/limiter state on loadBackingTrack so a new song
  doesn't inherit the previous track's gain follower and briefly mis-level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: integration test for the in-process plugin fault guard

Drives deliberately-faulting in-process AudioProcessors through a real
SignalChain::process() and asserts the host survives, the processor is released,
and it's added to the crash blocklist (shouldSandbox() then routes it
out-of-process). Covers BOTH fault kinds: a hardware SIGSEGV (POSIX guard /
Windows SEH) and a normal C++ exception (the path that must leave the guard
disarmed). End-to-end counterpart to the standalone mechanism check — exercises
the actual invokePlugin() guard.

Lives in the POSIX-only sandbox e2e harness (already links juce_audio_processors
+ the full sandbox set). Leak detection is disabled for the target because the
guard leaks the faulting processor by design.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jafz2001 <ignacio.fritis@mundotelecomunicaciones.cl>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Byron Gamatos <xasiklas@gmail.com>
2026-06-19 23:08:05 +02:00
facac93659 feat(brand): finish desktop chrome rebrand → fee[dB]ack (#23)
main/main split #21 already rebranded splash.html + the splash status
message. This finishes the remaining user-visible chrome:

- Window titles (both BrowserWindows): Slopsmith → fee[dB]ack
- Error dialogs: "failed to start" / "Please restart" (×4) + the
  Velopack updater-error dialog
- macOS mic-permission warning string
- crashReporter productName/companyName label
- package.json: productName → "fee[dB]ack" (+ safe executableName
  "feedback" and artifactName slug so the AppImage/deb filename and
  inner binary avoid the "[dB]" glob metacharacters), description,
  and NSMicrophoneUsageDescription

Deliberately unchanged for continuity:
- package.json "name" (config dir stays ~/.config/slopsmith-desktop —
  testers keep settings/cache) and "appId" (Velopack update identity)
- code comments + the [main] dev console.log

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 16:32:57 +02:00
K. O. A.andGitHub 4b7690b803 Merge pull request #21 from got-feedback/fix/splash-rebrand-feedback
Rebrand splash/loading dialog Slopsmith -> fee[dB]ack
2026-06-19 09:13:35 -04:00
topkoaandClaude Opus 4.8 9d424ece9d Rebrand splash/loading dialog Slopsmith -> fee[dB]ack
The startup splash window and its initial status message still showed
the old "Slopsmith" name. Update the brand label, the static status
line, and the JS fallback in splash.html, plus the main-process startup
status snapshot that overrides it, to the new "fee[dB]ack" branding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: topkoa <topkoa@gmail.com>
2026-06-19 08:56:26 -04:00
byrongamatosandClaude Opus 4.8 2655bbe364 Remove corrupt mesa_cab.wav IR (HTML, never a valid WAV)
The file was an HTML page (a failed download) committed in the very
first commit — never a valid impulse response, and not referenced by
name. Shipping it would feed garbage to the convolver if selected.
The 5 other bundled cab IRs are valid and unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:57:54 +02:00
byrongamatosandClaude Opus 4.8 ac8edbf9af Remove FUNDING.yml (no Sponsor button / funding surface)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:52:46 +02:00
byrongamatosandClaude Opus 4.8 b5784c20bb Repoint dead slopsmith URLs -> got-feedback
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:02:09 +02:00
byrongamatosandClaude Opus 4.8 d6007bdc3f build: bundle loosefolder + strum-fighter plugins
Add the re-homed feedback-plugin-loosefolder (dir override :loose_folder
since the plugin id is loose_folder) and feedback-plugin-strum-fighter
to the bundled set (now 36 plugins).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 09:50:10 +02:00
byrongamatosandClaude Opus 4.8 e59d68d3f2 ci: host soundfonts on the public feedback-soundfonts repo
feedback-desktop is private, so its release assets aren't fetchable by
the unauthenticated build curl or by end users at runtime. Move the
GeneralUser-GS + FluidR3_GM downloads to the public got-feedback/
feedback-soundfonts repo (freely-redistributable GM soundfonts, no
third-party content). Checksums unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 01:09:38 +02:00
byrongamatosandClaude Opus 4.8 0e7c428a9c ci: rename the cross-repo token secret to FEEDBACK_CLONE_TOKEN
Drop the stale slopsmith-era name now that everything lives under the
got-feedback org. Same secret, used for both the authenticated private
clones (GH_CLONE_TOKEN) and the VERSION-sync dispatch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:57:25 +02:00
byrongamatosandClaude Opus 4.8 28d9a7f30f ci: repoint desktop build off the deleted slopsmith org
The slopsmith org was deleted in the DMCA relaunch; core + plugins now
live under the private got-feedback org. Repoint the whole build:

- core clone (nightly.yml, build-common.sh) -> got-feedback/feedback,
  authenticated via GH_CLONE_TOKEN (a PAT with read on the private org;
  threaded through build.yml/nightly.yml/release.yml). Local builds
  without it fall back to the git credential helper.
- bundled-plugin list -> got-feedback/feedback-plugin-*, pruned to the
  set that exists in the org: drops the removed extraction plugins
  (profileimport, tones, sloppak-converter) and not-yet-rehomed ones
  (nam-rig-builder, tabimport); 34 plugins bundled.
- dirname derivation strips the new feedback-plugin- prefix.
- ghcr image -> ghcr.io/got-feedback/feedback; VERSION-sync dispatch
  -> got-feedback/feedback; soundfont + update FEED_URL + docs ->
  got-feedback/feedback-desktop.

Two prerequisites remain (owner-only): set the GH_CLONE_TOKEN secret,
and re-upload the soundfonts-v1 release assets to feedback-desktop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:47:43 +02:00
byrongamatosandClaude Opus 4.8 4238b70cf4 Restore .psarc in log-redaction extension list
The terminology rename swapped '.psarc' for '.archive' in the
log/telemetry filename-redaction regex. '.archive' is not a real
extension; real '.psarc' filenames on users' disks would stop being
scrubbed and could leak into logs/telemetry. This is a redaction
allow-list, not brand text.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 21:33:26 +02:00
Sin eadc2e0a32 Remove external game/format terminology from code and docs
Reword references in comments, docs and UI strings; no behaviour change.
2026-06-16 19:53:19 +01:00
Byron Gamatos bd603184d5 Clean release snapshot 2026-06-16 18:48:12 +02:00