# Tunnels

A phase-modulation reese bass synthesizer plugin. JUCE 8, C++20. Builds as
**VST3**, **AU**, and **Standalone** on macOS, Linux, and Windows.

- Manufacturer: Beige Threat (`Lflu` / `Tnnl`)
- Bundle ID: `com.beigethreat.tunnels`
- JUCE: 8.0.12 (fetched via CMake `FetchContent`)

## Who this is for

This repository is primarily for Beige Threat maintainers and coding agents
working on Tunnels, the shared Thanet design system, and the surrounding build,
test, packaging, and release tooling.

## Repository layout

| Path | Contents |
| --- | --- |
| `plugins/tunnels/src/` | Tunnels processor, presets, DSP, UI |
| `plugins/tunnels/src/dsp/` | Synth engine: `PDVoice`, filters, drive, FX, LFO, sequencer |
| `plugins/tunnels/src/ui/` | `Editor`, panels, composites, primitives, presenters, views |
| `plugins/tunnels/src/auth/` | `LicenseManager` (offline license card verification) |
| `modules/thanet/` | Internal JUCE design system (`thanet::thanet`); see its own README |
| `modules/bt_assets/` | Shared design-system BinaryData |
| `modules/bt_dsp/`, `modules/bt_auth/` | Shared native module landing zones |
| `plugins/tunnels/presets/` | XML preset bank shipped with Tunnels |
| `plugins/tunnels/tests/` | CTest suite and refs for Tunnels |
| `tools/` | Preset renderer, snapshot tools, license-card signing, pluginval/auval scripts |
| `plugins/tunnels/packaging/` | Tunnels installer recipes (`linux/`, `macos/`, `windows/`) |
| `docs/RELEASE.md` | Release Please workflow, tag automation, and release gates |
| `cmake/` | `Dependencies.cmake` (JUCE fetch and friends) |
| `fonts/`, `licenses/`, `design/` | Binary assets and design references |

## Prerequisites

The repo ships a Nix flake and `devenv.nix` — entering the dev shell gives you
the exact CMake, Ninja, clang-tools, `just`, `ccache`, `lefthook`, and (on
Linux) `pluginval` and the X11/ALSA build inputs.

```sh
nix develop          # or: direnv allow
```

Without Nix you need: CMake ≥ 3.22, Ninja, a C++20 compiler (Clang/AppleClang
or GCC), `just`, `ccache`, and JUCE's platform deps (ALSA, JACK, GTK3,
freetype, fontconfig, X11 libs on Linux).

## Common tasks

All routine work goes through `just`. Run `just` for the full list.

```sh
just build              # Debug build (configures if needed)
just build-fast         # Release VST3 + Standalone, no LTO, unity build, ccache
just test               # Run the unit test binary directly
just ctest              # Full CTest suite with verbose failures
just verify             # build + ctest + pluginval (the local "ready to push" gate)
just ci-local           # Mirror the hosted PR gate before spending CI minutes
just asan               # ASan + UBSan in build-asan/
just pluginval          # Validate built formats at strictness 10
just pluginval-install  # Install pluginval if the dev shell cannot provide it
just auval              # Apple AU validator (macOS only)
just format             # lefthook-driven formatting (matches the pre-commit hook)
just render-refs        # Regenerate plugins/tunnels/tests/refs/*.wav intentionally
```

Build artefacts land under `build/Tunnels_artefacts/<Format>/`. On macOS the
standalone is `build/Tunnels_artefacts/Standalone/Tunnels.app`.

## Build flags

| Option | Default | Purpose |
| --- | --- | --- |
| `BUILD_TESTING` | `ON` | Build the CTest suite |
| `TUNNELS_SANITIZERS` | `OFF` | ASan + UBSan on Tunnels targets |
| `TUNNELS_STRICT_WARNINGS` | `ON` | `-Wall -Wextra -Wshadow -Wconversion …` on our sources only |
| `TUNNELS_WERROR` | `OFF` | Treat strict warnings as errors (CI: ON) |
| `TUNNELS_ENABLE_COMPONENT_GALLERY` | `ON` | Compatibility option for snapshot tools |
| `TUNNELS_BUILD_TOOLS` | `ON` | Build `tunnels_preset_render` and friends |
| `TUNNELS_UNITY_BUILD` | `OFF` | Unity-build our `.cpp` files (JUCE TUs stay separate) |
| `TUNNELS_ENABLE_JUCE_LTO` | `ON` (Linux: `OFF`) | JUCE's recommended Release LTO |

Strict warnings are applied per-source so JUCE module TUs (pushed via
`INTERFACE_SOURCES`) compile cleanly.

## Development contracts

- **Parameters:** APVTS parameter IDs are shipped compatibility surface. Never
  rename or remove them; update presets and `PresetCatalogueTest` when adding
  parameter-facing behavior.
- **DSP:** `processBlock` and anything it calls must not allocate, lock, or
  throw. DSP-output changes must update render refs intentionally.
- **UI:** Prefer Thanet widgets, tokens, `ColourRole`, and `ShadowRole` before
  adding Tunnels-local styling.
- **Build:** Use `just` recipes and `bt_apply_strict_warnings(...)` per source;
  do not attach strict warnings to the whole JUCE plugin target.

## Testing

`plugins/tunnels/tests/` contains GoogleTest-style unit tests for the DSP primitives
(filters, LFO, limiter, smoothing, voice, aliasing, waveforms), the matrix
and sequencer, presets, license verification, and UI primitives. Render
references live in `plugins/tunnels/tests/refs/` — diff them with `just render`, regenerate
with `just render-refs`.

## Presets

Hand-authored XML presets live in `plugins/tunnels/presets/`. The catalogue is validated by
`PresetCatalogueTest`. Generated/scripted presets go through
`tools/gen_presets.py`. **Trap to watch for:** any preset with osc `DCW`
depth = 0 collapses to a cosine regardless of the selected waveform — always
co-check `wave` and `DCW depth` when auditing.

## Installation (built locally)

After a successful build, the platform-specific installer scripts under
`tools/install-{linux,macos,windows}.sh|bat` copy the built bundles into the
standard plugin paths.

## Further reading

- `docs/ARCHITECTURE.md` — module map, key conventions, and where to make
  changes.
- `docs/DOCS_GUIDE.md` — how to write concise repo docs and where each doc
  type belongs.
- `docs/ARCHITECTURE_TODO.md` — temporary post-refactor hardening backlog.
- `docs/UI_CONSISTENCY_BACKLOG.md` — temporary UI consistency backlog.
- `docs/ADDING_PLUGIN.md` — checklist for adding another Beige Threat plugin.
- `docs/DAW_INTEGRATION.md` — host-facing validation checklist.
- `modules/thanet/README.md` and `modules/thanet/docs/` — the internal design
  system.
