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
134 lines
7.1 KiB
Markdown
134 lines
7.1 KiB
Markdown
<!-- graft:start -->
|
||
## Graft — repo context graph
|
||
|
||
This repo is indexed in `graft/`: small linked markdown nodes that explain each
|
||
system and carry exact file:line spans, kept in sync with the code through git.
|
||
|
||
For ANY task here — understanding how something works, finding where code lives,
|
||
or scoping a change — get context from the graph before grepping or opening
|
||
source files. Re-ask freely (it's cheap) and reuse literal identifiers you
|
||
already have (symbol, error string, file name) as the query. New to this repo?
|
||
Run `graft map` first — a token-budgeted orientation (dir clusters, hubs,
|
||
hotspots), no LLM, no key.
|
||
|
||
- Run `graft ask "<your question>" --source` → ranked nodes with the relevant
|
||
code spans inlined (each hit's ≤8-line crux by default; `--full` for whole
|
||
definitions when the crux isn't enough). Match the tool to the task shape:
|
||
for understanding or editing, the top node IS the answer — cite its
|
||
`covers:` file:line spans and edit straight from `--source`. For
|
||
exhaustive tasks ("every occurrence / every caller of this pattern"), ranked
|
||
results are top-N, not complete — run `graft grep "<literal>"` instead
|
||
(exhaustive over indexed files, grouped by enclosing symbol), falling back
|
||
to raw `grep -rn` only for unindexed files.
|
||
- `graft skeleton <file>` → every definition's signature + span, ~10× cheaper
|
||
than reading the file; use it to skim an API surface.
|
||
- `graft callers <symbol>` gives precomputed, exact edges — who calls this.
|
||
Add `--direction out` for what it calls, or `--depth N` to walk
|
||
transitively for the full blast radius. For structural questions, skip
|
||
ranking and use this directly.
|
||
- Or browse: `graft/INDEX.md` lists every node; follow the links.
|
||
- Monorepos and folders of multiple repos rank fairly across sub-projects —
|
||
hits carry `[scope/]` labels naming which one they're from. Narrow with
|
||
`graft ask "<task>" --in <scope>/` once you know where you're working.
|
||
|
||
If a returned span is truncated ("+N more lines"), open the file at that exact
|
||
range before finalizing. Only open source files when a node genuinely lacks a
|
||
needed detail, and then at the exact file:line the node points to — never
|
||
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.
|