chore: land janitor round 1 and graft integration

Round 1 findings and fixes, all previously uncommitted:
- FXProcessor per-slot DSP history repair (HEAD does not compile without it)
- SynthVoice::getModulationValue, editor control-lock guard
- ExactCompare.h naming the deliberate exact float comparisons
- KnobLookAndFeel replacing the never-installed SerumLookAndFeel
- 55 first-party compiler warnings to 0
- AGENT.md renamed to AGENTS.md across Source/
- graft repository context graph and its hooks
- JANITOR_TASKS.md and UI_UX_AUDIT.md records
This commit is contained in:
biggy committed 2026-10-06 08:50:45 +02:00
1 parent 5c942cad0c
commit e4cea300db
63 files changed
+2360 -805

No files matched your search

+92
View File
@@ -39,3 +39,95 @@ re-read whole files.
After big code changes, refresh the graph with `graft build` (deterministic,
no API key, $0).
<!-- graft:end -->
# SerumAlt agent guidance
## Project
SerumAlt is a JUCE 7 wavetable synthesiser using C++17. Project metadata is in
`CMakeLists.txt`. Production formats are VST3 and Standalone on Linux, VST3/AU/Standalone
on macOS, and VST3 on Windows. First-party classes use `namespace serum`; executable
entry points and JUCE's `createPluginFilter` are outside that namespace.
## Development scope
This is a fun proof of concept. Prefer small working changes, clear names, and
successful compilation over release engineering or broad rewrites. Use the existing
smoke harness for DSP changes; add test infrastructure only when requested. The user
will judge sound and interaction by using the synth. Keep ownership and audio-thread
safety fixes practical, without adding a generic framework.
## Build and verification
Read README.md's Building section before changing scripts, dependencies, or CMake.
It is the maintained source for prerequisites, options and artifact paths.
- Linux production: `./build_linux.sh`.
- macOS production, on a Mac: `./build_macos.sh`.
- Windows x64 VST3, cross-compiled on Linux: `./build_windows.sh`.
- Native QA build and execution: `./build_harness.sh --run`.
- Shell syntax: `for script in build_*.sh; do bash -n "$script"; done`.
Production scripts explicitly enable `SERUMALT_BUILD_PLUGIN` and disable
`SERUMALT_BUILD_TESTS`. The harness script does the reverse in a separate directory.
Building `SerumAltTest` alone does not execute it; `--run` invokes CTest.
When changing CMake, verify production has no `SerumAltTest` target and the
harness-only build has no `SerumAlt`, VST3, AU, or Standalone target.
Keep existing build trees and local changes intact. Use a new `BUILD_DIR` for
clean-build verification. Use a fresh Windows `OUTPUT_DIR` for distribution checks,
since staging does not remove extra files. Never edit generated CMakeCache.txt files.
The checked-in MinGW toolchain is the single source of cross-compiler configuration.
## Current source layout
`CMakeLists.txt` owns the explicit `SERUMALT_SOURCES` list and shared target setup.
`cmake/Plugin.cmake` owns production formats and MinGW link flags;
`cmake/Harness.cmake` owns the console harness and CTest registration.
The harness compiles the same processor/editor sources independently of the plugin.
Most C++ files still live directly under `Source/`. Existing implementation
subdirectories are `EffectUnits/`, `GUI/`, `Presets/`, `Resources/`, and `Tests/`.
`FXProcessor`, `PluginEditor`, `Resources`, and `RAVEButton` remain at the source root.
`RAVEButton.{h,cpp}` defines `RaveController`.
The lowercase `Source/engine`, `modulation`, `params`, `plugin`, and `synth`
directories currently hold guidance, not relocated implementations. Consult their
`AGENTS.md` files when editing the related root-level sources. Consult the matching
`AGENTS.md` when editing an existing implementation subdirectory.
`AUDIT_REPORT.md` is a historical audit and proposed refactor, not a pending
instruction to move files. Update the explicit source list and includes only when
an actual source move is part of the requested task.
## Style and ownership
Follow the surrounding file. Existing C++ generally uses four-space indentation,
`#pragma once`, PascalCase types, camelCase members without prefixes, `k`-prefixed
constants, scoped enums, and `noexcept` on cheap getters and DSP paths. Use `Count`
only for enums that need a size or iteration sentinel. Headers include JuceHeader;
implementation files normally include their own header first.
Prefer value members or `std::unique_ptr` for owned objects and attachments.
`addAndMakeVisible` does not transfer ownership or delete children. Raw allocations
returned by `createEditor` and `createPluginFilter` transfer ownership to JUCE callers.
Guard parameter lookups and invalid state data. Use `jassert` sparingly for programmer
errors and return `bool` from bounded inserts to report failure.
## Real-time and concurrency requirements
For new or changed audio paths, allocate buffers during preparation and avoid heap
allocation, blocking locks and I/O in `processBlock` or per-sample DSP. Account for
variable host block sizes without allocating in the callback. Keep GUI updates on
the JUCE message thread. Exchange GUI/audio state through a safe snapshot or bounded
handoff; a timer or a writer-only mutex does not make concurrent access safe.
The engine prebuilds wavetables and renders through bounded buffer views. GUI and
state edits hold `Engine::getControlLock()`; audio uses a try-lock to capture into
reserved storage and keeps its last snapshot when busy. Keep those two copies
separate. RAVE changes render settings, not the underlying knob values. The
historical audit describes the older implementation, not current behavior.
## Scope of guidance
Module guidance refines this file for its related sources. Preserve the root
real-time and ownership requirements if an example conflicts with them.