Skip to content

Commit ca01464

Browse files
committed
Release 0.5 (WIP)
- Add reusable framework modules for upcoming 0.5 models, including DramaBox, RVC, Confucius4-TTS, Kroko ASR, and related encoder/vocoder paths - Refactor DramaBox, RVC, and Confucius4-TTS toward spec v1 backed model loading and shared framework components - Add framework support for Zipformer, Gemma decoder, Wav2Vec2-BERT, RMVPE, BigVGAN extensions, attention/norm/activation modules, and text normalization - Update model specs and path-test coverage for migrated/new models - Update WebUI model handling so default downloads use GGUF packages from model specs while existing local tensor installs remain loadable - Add WebUI catalog/download tests and model parameter entries for newly exposed models
1 parent 9ca7d62 commit ca01464

110 files changed

Lines changed: 8211 additions & 7300 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ add_library(engine_core OBJECT
253253
src/framework/text/chinese_normalization.cpp
254254
src/framework/text/chunking.cpp
255255
src/framework/text/subtitle.cpp
256+
src/framework/text/text_normalization.cpp
256257
src/framework/text/unicode_normalization.cpp
257258
src/framework/io/yaml.cpp
258259
src/framework/io/binary.cpp
@@ -272,12 +273,15 @@ add_library(engine_core OBJECT
272273
src/framework/modules/structural_modules.cpp
273274
src/framework/modules/asr_helpers.cpp
274275
src/framework/modules/conv_modules.cpp
276+
src/framework/modules/zipformer_modules.cpp
275277
src/framework/modules/speech_encoders/whisper_embedding.cpp
276278
src/framework/modules/speech_encoders/whisper_frontend.cpp
277279
src/framework/modules/speech_encoders/campplus_encoder.cpp
280+
src/framework/modules/pitch_extractors/rmvpe_pitch_extractor.cpp
278281
src/framework/modules/vocoders/bigvgan_vocoder.cpp
279282
src/framework/modules/vocoders/hift_vocoder.cpp
280283
src/framework/modules/speech_encoders/hubert_encoder.cpp
284+
src/framework/modules/speech_encoders/wav2vec2_bert_encoder.cpp
281285
src/framework/modules/speech_encoders/wavlm_encoder.cpp
282286
src/framework/modules/speech_encoders/sanm.cpp
283287
src/framework/modules/optimizations/fast_conv_modules.cpp
@@ -293,6 +297,7 @@ add_library(engine_core OBJECT
293297
src/framework/modules/attention/relative_attention.cpp
294298
src/framework/modules/attention/scaled_dot_product_attention.cpp
295299
src/framework/modules/attention/grouped_query_attention.cpp
300+
src/framework/modules/attention/projected_grouped_self_attention.cpp
296301
src/framework/modules/attention/streaming_frame_attention_cache.cpp
297302
src/framework/modules/transformers/qwen_decoder.cpp
298303
src/framework/modules/transformers/qwen_causal_decoder.cpp
@@ -304,6 +309,7 @@ add_library(engine_core OBJECT
304309
src/framework/modules/positional_modules.cpp
305310
src/framework/modules/text_encoders/t5_base_encoder.cpp
306311
src/framework/modules/text_encoders/t5_gemma_encoder.cpp
312+
src/framework/modules/transformers/gemma_decoder.cpp
307313
src/framework/modules/optimizations/fast_kv_modules.cpp
308314
src/framework/tokenizers/hf_tokenizer_json.cpp
309315
src/framework/tokenizers/llama_bpe.cpp
@@ -681,12 +687,11 @@ audiocpp_add_model(dramabox
681687
src/models/dramabox/gemma_tokenizer.cpp
682688
src/models/dramabox/gemma3_encoder.cpp
683689
src/models/dramabox/latent_state.cpp
684-
src/models/dramabox/loader.cpp
685690
src/models/dramabox/prompt_connector.cpp
686691
src/models/dramabox/session.cpp
687692
src/models/dramabox/vocoder.cpp
688693
INCLUDES
689-
engine/models/dramabox/loader.h
694+
engine/models/dramabox/session.h
690695
LOADERS
691696
engine::models::dramabox::make_dramabox_loader
692697
)
@@ -1001,9 +1006,8 @@ audiocpp_add_model(rvc
10011006
src/models/rvc/session.cpp
10021007
src/models/rvc/synthesizer.cpp
10031008
src/models/rvc/voice_model.cpp
1004-
src/models/rvc/loader.cpp
10051009
INCLUDES
1006-
engine/models/rvc/loader.h
1010+
engine/models/rvc/session.h
10071011
LOADERS
10081012
engine::models::rvc::make_rvc_loader
10091013
)
@@ -1497,6 +1501,13 @@ if (ENGINE_BUILD_TESTS)
14971501
COMMAND unicode_normalization_test
14981502
)
14991503

1504+
add_engine_unittest(text_normalization_test tests/unittests/test_text_normalization.cpp)
1505+
1506+
add_test(
1507+
NAME text_normalization_test
1508+
COMMAND text_normalization_test
1509+
)
1510+
15001511
add_engine_unittest(outetts_generation_budget_test tests/unittests/test_outetts_generation_budget.cpp)
15011512
target_include_directories(outetts_generation_budget_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/unittests)
15021513

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ Runtime tags: safetensors is the default model loading path. `GGUF 16/Q8/Q4` mea
5656

5757
| Family | Task | Lang | Variants | Runtime |
5858
|---|---|---|---|---|
59-
| **ace_step** | Music, Edit | 50+ langs | ACE-Step 1.5 Turbo and Base with acestep-5Hz-lm-1.7B | GGUF 16/Q8 |
59+
| **ace_step** | Music, Edit | 50+ langs | ACE-Step 1.5 Turbo and Base with acestep-5Hz-lm-1.7B | GGUF 16 |
6060
| **bs_roformer** | Sep | lang agnostic | BS-RoFormer vocal separation checkpoints | GGUF Q8 |
6161
| **chatterbox** | TTS, Clone, VC| ar, da, de, el, en, es, fi, fr, hi, it, ko, ms, nl, no, pl, pt, sv, sw, tr | Chatterbox with 0.5B backbone | GGUF 16/Q8 |
62+
| **confucius4_tts** | Clone | zh, en, ja, ko, de, fr, es, id, it, th, pt, ru, ms, vi | Confucius4-TTS multilingual voice cloning | GGUF F32, Stream |
6263
| **citrinet_asr** | ASR | en | Citrinet-256 | GGUF Q8 |
64+
| **dramabox** | TTS, Clone | en | DramaBox expressive TTS and voice cloning | GGUF Q8 |
6365
| **fish_audio** | TTS, Clone, Ctrl | auto, en, zh | Fish Audio S2 Pro | GGUF 16/Q8 |
6466
| **fun_asr_nano** | ASR | auto, zh, en, ja | Fun-ASR-Nano-2512 | GGUF 16/Q8 |
6567
| **heartmula** | Music | zh, en, ja, ko, es | HeartMuLa-oss-3B with HeartCodec-oss | GGUF 16/Q8 |
@@ -77,6 +79,7 @@ Runtime tags: safetensors is the default model loading path. `GGUF 16/Q8/Q4` mea
7779
| **qwen3_asr** | ASR | zh, en, yue, ar, de, fr, es, pt, id, it, ko, ru, th, vi, ja, tr, hi, ms, nl, sv, da, fi, pl, cs, fil, fa, el, ro, hu, mk | Qwen3-ASR-0.6B, Qwen3-ASR-1.7B-hf | GGUF 16/Q8 |
7880
| **qwen3_forced_aligner** | Align | zh, yue, en, de, es, fr, it, pt, ru, ko, ja | Qwen3-ForcedAligner-0.6B | GGUF 16/Q8 |
7981
| **qwen3_tts** | TTS, Clone, Design, Ctrl | zh, en, fr, de, it, ja, ko, pt, ru, es | Qwen3-TTS-12Hz-0.6B-Base, Qwen3-TTS-12Hz-1.7B-Base, Qwen3-TTS-12Hz-1.7B-CustomVoice, Qwen3-TTS-12Hz-1.7B-VoiceDesign | GGUF 16/Q8 |
82+
| **rvc** | VC | lang agnostic | RVC F16 GGUF with packaged v1/v2 voices and optional retrieval blending | GGUF 16 |
8083
| **seed_vc** | VC | lang agnostic | SeedVC XLS-R + HiFT, SeedVC Whisper-small + BigVGAN | GGUF 16/Q8 |
8184
| **silero_vad** | VAD | lang agnostic | Silero VAD | Bundled, Stream |
8285
| **sortformer_diar** | Diar | en | Sortformer-4spk-v1 | - |
@@ -626,7 +629,7 @@ For long-form TTS tests, each run uses the same 6,026-character, 1,028-word inpu
626629

627630
## Runtime Memory Options
628631

629-
Some models expose memory-saver session options such as `ace_step.mem_saver=true`, `heartmula.mem_saver=true`, `stable_audio.mem_saver=true`, `omnivoice.mem_saver=true`, and `voxcpm2.mem_saver=true`. These options keep the default output path unchanged while reducing graph workspace VRAM or releasing staged graph/cache state after request phases; later requests may rebuild released graphs.
632+
Some models expose memory-saver session options such as `ace_step.mem_saver=true`, `dramabox.mem_saver=true`, `heartmula.mem_saver=true`, `stable_audio.mem_saver=true`, `omnivoice.mem_saver=true`, and `voxcpm2.mem_saver=true`. These options keep the default output path unchanged while reducing graph workspace VRAM or releasing staged graph/cache state after request phases; later requests may rebuild released graphs.
630633

631634
## Precision/Quantization Support
632635

docs/asr.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
| Higgs Audio STT | `higgs_audio_stt` | offline, streaming | [Higgs Audio STT](#higgs-audio-stt) |
1010
| Hviske ASR | `hviske_asr` | offline | [Hviske ASR](#hviske-asr) |
1111
| Nemotron ASR | `nemotron_asr` | offline, streaming | [Nemotron ASR](#nemotron-asr) |
12+
| Parakeet-TDT | `parakeet_tdt` | offline, streaming | [Parakeet-TDT](#parakeet-tdt) |
1213
| VibeVoice ASR | `vibevoice_asr` | offline | [VibeVoice ASR](#vibevoice-asr) |
1314
| Voxtral Realtime | `voxtral_realtime` | offline, streaming | [Voxtral Realtime](#voxtral-realtime) |
1415

@@ -87,26 +88,23 @@ joiner, greedy search, and modified beam search natively without ONNX Runtime.
8788
Blank penalty, natural-text hotwords, and opt-in endpoint segmentation are
8889
available as request options. Public free packages
8990
are available for German, English, Spanish, French, Italian, Hebrew, Dutch,
90-
Portuguese, Swedish, and Turkish. Download the matching free Kroko Community
91-
`.data` package and convert it before use:
91+
Portuguese, Swedish, and Turkish. The model manager defaults to the standalone
92+
English Q8_0 GGUF package:
9293

9394
```powershell
94-
python .\tools\community_models\convert_kroko_onnx.py `
95-
.\models\Kroko-ASR\Kroko-EN-Community-128-L-Streaming-001.data `
96-
.\models\Kroko-ASR\Kroko-EN-Community-128-L-Native `
97-
--overwrite
95+
python .\tools\model_manager.py install kroko_asr_community_q8_0 --models-root .\models --overwrite
9896
```
9997

10098
```powershell
10199
.\build\windows-cuda-release\bin\audiocpp_cli.exe `
102100
--task asr --mode streaming --family kroko_asr `
103-
--model .\models\Kroko-ASR\Kroko-EN-Community-128-L-Native `
101+
--model .\models\Kroko-ASR-GGUF\kroko-en-community-64-l-q8_0.gguf `
104102
--backend cuda --audio .\speech.wav --language en `
105103
--text-out .\transcript.txt --words-out .\words.json
106104
```
107105

108-
Converted safetensors and standalone Q8 GGUF are supported in offline and
109-
stateful streaming modes. Partial transcripts and word timestamps are exposed.
106+
Standalone Q8 GGUF is supported in offline and stateful streaming modes. Partial
107+
transcripts and word timestamps are exposed.
110108
See [Kroko Community ASR](community_models/kroko_asr.md) for package selection,
111109
conversion, GGUF, decoding options, parity, performance, and limitation details.
112110

@@ -250,6 +248,23 @@ audiocpp_cli --task asr --family nemotron_asr --model models/nemotron-3.5-asr-st
250248
| `--text-out` | TXT path | not set | Transcript output. The transcript is also printed to stdout. |
251249
| `--session-option nemotron_asr.mem_saver=true|false` | bool | `false` | Release the offline encoder graph after each offline request. |
252250

251+
## Parakeet-TDT
252+
253+
Parakeet-TDT is a FastConformer-TDT ASR model for multilingual offline,
254+
long-form, and buffered-streaming transcription. The model manager defaults to
255+
the standalone Q8_0 GGUF package.
256+
257+
```bash
258+
python3 tools/model_manager.py install parakeet_tdt_q8_0 --models-root models
259+
audiocpp_cli --task asr --family parakeet_tdt \
260+
--model models/Parakeet-TDT-0.6B-v3-GGUF/parakeet-tdt-0.6b-v3-q8_0.gguf \
261+
--backend cuda --audio speech_16k.wav --text-out transcript.txt
262+
```
263+
264+
Use `parakeet_tdt_f16` for the F16 GGUF variant. See
265+
[Parakeet-TDT 0.6B v3](community_models/parakeet_tdt.md) for long-form,
266+
streaming, conversion, options, validation, and performance details.
267+
253268
## VibeVoice ASR
254269

255270
VibeVoice ASR is an offline ASR model with greedy, sampling, and beam-search decode paths. It can return transcription text and structured segment/speaker-turn output when the model produces timestamps.

docs/audio_tools.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
| Model | Family | Task(s) | Quick Start |
44
|---|---|---|---|
55
| MioCodec | `miocodec` | `vc`, `s2s` | [MioCodec](#miocodec) |
6+
| RVC | `rvc` | `vc` | [RVC](#rvc) |
67
| Seed-VC | `seed_vc` | `vc`, `svc` | [Seed-VC](#seed-vc) |
78
| VeVo2 | `vevo2` | TTS, SVC, VC, editing | [VeVo2](#vevo2) |
89
| HTDemucs | `htdemucs` | `sep` | [HTDemucs](#htdemucs) |
@@ -51,6 +52,62 @@ audiocpp_cli --task s2s --family miocodec --model models/MioCodec-25Hz-44.1kHz-v
5152
| `--out` | WAV path | required | Output audio path. |
5253
| `--session-option miocodec.weight_type=<type>` | `native`, `f32`, `f16`, `bf16`, `q8_0` | `native` | Model weight type when supported by each component. |
5354

55+
## RVC
56+
57+
RVC is an offline retrieval-based voice-conversion model. The audio.cpp package
58+
uses native HuBERT content features, RMVPE pitch extraction, optional IVF
59+
retrieval blending, and packaged v1/v2 voices. The F16 GGUF package is
60+
self-contained and embeds the package spec plus packaged retrieval sidecars.
61+
62+
| Field | Value |
63+
|---|---|
64+
| Family | `rvc` |
65+
| GGUF model | `models/RVC-GGUF/rvc-f16.gguf` |
66+
| Task | `vc` |
67+
| Modes | `offline` |
68+
| Input | Source speech WAV through `--audio` |
69+
| Packaged voices | `default`, `manthos`, `chocola`, `fraise` |
70+
| Output | Single converted WAV through `--out` |
71+
72+
Packaged voice without retrieval:
73+
74+
```bash
75+
audiocpp_cli --task vc --family rvc --model models/RVC-GGUF/rvc-f16.gguf --backend cuda --audio source.wav --out converted.wav --request-option voice_id=default
76+
```
77+
78+
Packaged voice with retrieval blending:
79+
80+
```bash
81+
audiocpp_cli --task vc --family rvc --model models/RVC-GGUF/rvc-f16.gguf --backend cuda --audio source.wav --out converted.wav --request-option voice_id=default --request-option retrieval_blend=0.5
82+
```
83+
84+
User RVC checkpoint with a matching FAISS retrieval index:
85+
86+
```bash
87+
audiocpp_cli --task vc --family rvc --model models/RVC-GGUF/rvc-f16.gguf --backend cuda --audio source.wav --out converted.wav --request-option voice_model_path=/path/to/voice.pth --request-option retrieval_index_path=/path/to/voice.index --request-option retrieval_blend=0.5
88+
```
89+
90+
| Option | Values | Default | Meaning |
91+
|---|---|---:|---|
92+
| `--request-option voice_id=<id>` | `default`, `manthos`, `chocola`, `fraise` | `default` | Packaged RVC voice id. Ignored when `voice_model_path` is set. |
93+
| `--request-option voice_model_path=<path>` | `.pth` or `.pt` path | unset | User RVC checkpoint path. |
94+
| `--request-option pitch_extractor=rmvpe` | `rmvpe` | `rmvpe` | Pitch extractor for F0-enabled voices. |
95+
| `--request-option pitch_path=<path>` | CSV path | unset | Optional F0 override file with `time,Hz` rows sorted by time. |
96+
| `--request-option retrieval_index_path=<path>` | FAISS `.index` path | unset | User retrieval index used when `retrieval_blend` is greater than 0 for a user checkpoint. |
97+
| `--request-option retrieval_blend=<rate>` | `0.0` to `1.0` | `0.0` | IVF retrieval feature blend rate. `0` disables retrieval. |
98+
| `--request-option semitone_shift=<n>` | integer | `0` | Semitone pitch shift before synthesis. |
99+
| `--request-option pitch_filter_radius=<n>` | integer >= 0 | `3` | Median filter radius for F0 smoothing; values greater than 2 enable filtering. |
100+
| `--request-option output_sample_rate=<hz>` | integer >= 0 | `0` | Output sample rate; `0` keeps the selected voice model sample rate. |
101+
| `--request-option rms_mix_rate=<rate>` | float | `0.25` | RMS envelope mix rate after conversion. |
102+
| `--request-option unvoiced_protection=<rate>` | `0.0` to `1.0` | `0.33` | Unvoiced consonant protection strength. |
103+
| `--request-option speaker_id=<n>` | integer >= 0 | `0` | Speaker embedding id for multi-speaker checkpoints. |
104+
| `--request-option audio_pad_duration_sec=<sec>` | integer >= 1 | `1` | Long-audio chunk pad duration. |
105+
| `--request-option split_query_sec=<sec>` | integer >= 1 | `5` | Quiet-point query window for long-audio splitting. |
106+
| `--request-option split_center_sec=<sec>` | integer >= 1 | `30` | Long-audio split center stride. |
107+
| `--request-option split_threshold_sec=<sec>` | integer >= 1 | `32` | Input duration before quiet-point splitting is used. |
108+
| `--session-option rvc.weight_type=<type>` | `native`, `f32`, `f16`, `bf16`, `q8_0` | `f32` | Tensor storage type for native RVC, HuBERT, and RMVPE weights. |
109+
| `--session-option rvc.voice_cache_slots=<n>` | integer >= 0 | `4` | User voice model cache slots. Set `0` to disable caching. |
110+
54111
## Seed-VC
55112

56113
Seed-VC provides voice conversion and singing voice conversion routes. See [Seed-VC](models/seed_vc.md) for the full route manual.

docs/community_models/inflect_v2.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Inflect Micro v2 and Nano v2
22

3+
Default model-manager downloads use the published GGUF package when available;
4+
the original source/conversion instructions below remain valid for manual use.
5+
36
`inflect_v2` provides native GGML inference for the English
47
[Inflect Micro v2](https://huggingface.co/owensong/Inflect-Micro-v2) and
58
[Inflect Nano v2](https://huggingface.co/owensong/Inflect-Nano-v2) TTS models.

docs/community_models/kroko_asr.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Kroko Community ASR
22

3+
Default model-manager downloads use the published GGUF package when available;
4+
the original source/conversion instructions below remain valid for manual use.
5+
36
`kroko_asr` is a native audio.cpp port of the free Kroko Community
47
Zipformer2/RNN-T models. The Kaldi-compatible filterbank, streaming
58
Conv2dSubsampling/ConvNeXt encoder, 19-layer Zipformer2, stateless predictor,

docs/community_models/parakeet_tdt.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Parakeet-TDT 0.6B v3
22

3+
Default model-manager downloads use the published GGUF package when available;
4+
the original source/conversion instructions below remain valid for manual use.
5+
36
FastConformer-TDT ASR port of NVIDIA's [`nvidia/parakeet-tdt-0.6b-v3`](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3)
47
(0.6B params, 25 European languages with auto language detection). The default
58
package uses the repository's Transformers-compatible `model.safetensors`

docs/gguf.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Status labels:
5656

5757
| Family | Package-spec refactor | Safetensors tested after refactor | `orig` GGUF tested | 16-bit GGUF tested | `q8_0` GGUF tested |
5858
|---|---|---|---|---|---|
59-
| `ace_step` | Done | Pass | --- | Pass (drift) | Pass (drift) |
59+
| `ace_step` | Done | Pass | --- | Pass (drift) | No (planner sampling can fail) |
6060
| `bs_roformer` | Done | Pass | --- | --- | Pass |
6161
| `chatterbox` | Done | Pass | --- | Pass (ASR match, drift) | Pass (ASR match, drift) |
6262
| `citrinet_asr` | Done | Pass | --- | --- | Pass |
@@ -88,6 +88,7 @@ Status labels:
8888
| `qwen3_tts` base | Done | Pass | Pass | Pass (ASR match, drift) | Pass (ASR match, drift) |
8989
| `qwen3_tts` custom voice | Done | Pass | --- | Pass (ASR match, drift) | Pass (ASR match, drift) |
9090
| `qwen3_tts` voice design | Done | Pass | --- | Pass (ASR match, drift) | Pass (ASR match, drift) |
91+
| `rvc` | Done | --- | --- | Pass | --- |
9192
| `seed_vc` | Done | Pass | --- | Pass (drift) | Pass (drift) |
9293
| `silero_vad` | Skip (tiny model) | --- | --- | --- | --- |
9394
| `sortformer_diar` | Done | Pass | --- | Pass | Pass |

docs/maintainers/model_specs.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ The only accepted spec shapes are the current source-layout specs already used
88
by production models, and the typed schema shown here for new metadata/catalog
99
work.
1010

11+
## Migration Trees
12+
13+
`model_specs/*.json` is the authoritative runtime tree. Specs with
14+
`schema_version: 1` in this directory are active typed specs and participate in
15+
`model_contract()` validation, embedded GGUF metadata, CLI/server inspection,
16+
and package discovery.
17+
18+
`model_specs_v1/*.json` is a migration reference tree only. It records the
19+
expected typed shape for families that have not moved to the v1 runtime contract
20+
yet. Do not treat it as an active runtime source, and do not assume changes there
21+
affect loaders, CLI options, server validation, or package installs until the
22+
family is migrated into `model_specs/` with `schema_version: 1`.
23+
24+
During migration, keep public option keys aligned with the code path that will
25+
actually consume them. If a live loader still accepts an older public key, either
26+
migrate the runtime to the normalized key in the same change or keep the legacy
27+
key out of the active spec until cutover. Avoid creating UI-only aliases.
28+
1129
## Typed Schema
1230

1331
Top-level fields:
@@ -155,6 +173,9 @@ Required dependencies are unconditional. Optional dependencies must declare
155173
typed `required_when` rows. Each row is a condition over a public option key.
156174
Common request keys such as `return_timestamps` stay unprefixed; model-specific
157175
keys stay namespaced. The dependency is needed when any row matches.
176+
`dependencies[].option` must name a declared option in the dependency `scope`,
177+
and every `required_when[].option_key` must refer to a declared public option in
178+
the referenced scope. Multiple `required_when` rows use OR semantics.
158179

159180
```json
160181
{

0 commit comments

Comments
 (0)