Layout: - scripts/ holds the four build scripts plus the new clean.sh - cmake/ holds mingw64-toolchain.cmake - the scripts default to build/linux, build/macos, build/windows, build/harness - docs/ holds the audit documents, with the round 1 task list archived Cleanup: - scripts/clean.sh removes generated output, with --dry-run, --staging, --legacy and --all, and refuses tracked, protected or outside paths - the Windows VST3 manifest now comes from cmake/moduleinfo.json.in, so its version, vendor and class IDs follow cmake/Plugin.cmake instead of a hand-written heredoc that could drift - deleted the unused Source/GUI/Slider, which no code constructed - fixed the hidden double processBlock overload: three warning lines to zero - unslopped the build scripts, the two .cjs helpers and the CMake comments - .gitignore covers the upstream JUCE Projucer and DemoRunner binaries Verified: five scripts pass bash -n; the harness passes CTest with zero warning lines; the Linux VST3 and Standalone link; the Windows cross-build passes its x86-64, runtime-import and entry-point checks; each configure exposes only its own targets; and a full build leaves Source/ and third_party/JUCE unchanged. The generated manifest is identical to the previous hand-written one.
136 lines
7.3 KiB
Markdown
136 lines
7.3 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: `./scripts/build_linux.sh`.
|
||
- macOS production, on a Mac: `./scripts/build_macos.sh`.
|
||
- Windows x64 VST3, cross-compiled on Linux: `./scripts/build_windows.sh`.
|
||
- Native QA build and execution: `./scripts/build_harness.sh --run`.
|
||
- Shell syntax: `for script in scripts/*.sh; do bash -n "$script"; done`.
|
||
- Build output removal: `./scripts/clean.sh --dry-run`, then the flags you need.
|
||
|
||
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. Each script defaults to a
|
||
directory under `build/`; 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
|
||
`cmake/mingw64-toolchain.cmake` 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.
|
||
`docs/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.
|