Skip to content

Commit 842b9d9

Browse files
roomi-fieldsclaude
andcommitted
feat(surface): add expects control-nature hint to device entries (0.11.0)
Each surface entry (cc_params + sysex params) may carry an `expects` field describing the device-side nature of the control — continuous (default), switch, momentary, trigger, clock, discrete. Purely informative: osc-bridge emits identical bytes and adds no runtime behaviour. The signal realization (CV/Gate/Trig/Clock) is the caller's concern, keeping osc-bridge universal. The field is open (any string accepted); recommended vocabulary documented in DEVICE_JSON_SCHEMA.md. - device.rs: `expects` on CcParamEntry + ParamEntry, default "continuous" - mcp.rs: list_routes returns `expects`; new tests for default + exposure - build_device_index.py: per-nature counts in devices.json - annotate Subsequent 37 (20 switch / 15 discrete / 2 trigger) + Osmose (3 momentary pedals); all other entries default to continuous Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 798c73d commit 842b9d9

13 files changed

Lines changed: 199 additions & 14 deletions

File tree

.claude-plugin/plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
33
"name": "osc-bridge",
4-
"version": "0.10.1",
4+
"version": "0.11.0",
55
"description": "Declarative OSC ↔ MIDI/SysEx bridge for 849 hardware synthesizers and music software (Ableton, Bitwig, Reaper, Sonic Pi, SuperCollider, Pure Data). A MIDI MCP and OSC MCP — discover the device catalogue, read a device's OSC surface, and send OSC to synths and DAWs from Claude.",
66
"author": {
77
"name": "roomi-fields",
@@ -30,7 +30,7 @@
3030
"mcpServers": {
3131
"osc-bridge": {
3232
"command": "npx",
33-
"args": ["-y", "@roomi-fields/osc-bridge@0.10.1", "mcp"]
33+
"args": ["-y", "@roomi-fields/osc-bridge@0.11.0", "mcp"]
3434
}
3535
}
3636
}

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,30 @@ additive minor bumps every time a new device class surfaces something
99
the JSON can't yet express. Backwards-compat of existing device JSONs
1010
is tracked explicitly under each release.
1111

12+
## [0.11.0] — 2026-06-24
13+
14+
Adds a control-nature hint to the device surface, so a caller can tell what
15+
each control *expects* without guessing from the range alone.
16+
17+
### Added — surface schema
18+
- Every surface entry (`cc_params.entries[]` and SysEx `params.entries[]`) may
19+
carry an **`expects`** field describing the device-side nature of the control:
20+
`continuous` (default), `switch`, `momentary`, `trigger`, `clock`, `discrete`.
21+
- It is **purely informative**: osc-bridge emits the exact same bytes regardless
22+
and adds no runtime behaviour. The signal realization (CV / Gate / Trig /
23+
Clock) is the caller's concern — osc-bridge stays universal and only states the
24+
device-side expectation. The field is open (any string is accepted) and the
25+
recommended vocabulary is documented in `DEVICE_JSON_SCHEMA.md`.
26+
- `list_routes` (MCP) now returns `expects` on every cc/sysex entry; the live
27+
`devices.json` index carries per-nature counts.
28+
- Annotated the first drivers where it is meaningful: Subsequent 37 (switches,
29+
stepped selectors, arpeggiator/panic triggers) and Osmose (pedals → momentary).
30+
31+
### Compatibility
32+
- Device JSONs: unchanged behaviour — every unannotated entry is `continuous`,
33+
so all `0.10.x` drivers load and emit identically. The 849-driver catalogue is
34+
byte-compatible at runtime.
35+
1236
## [0.10.1] — 2026-05-14
1337

1438
A polish release for the MCP server. No device-JSON or runtime changes.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "osc-bridge"
3-
version = "0.10.1"
3+
version = "0.11.0"
44
edition = "2021"
55
description = "Declarative OSC ↔ MIDI/SysEx bridge for hardware synthesizers"
66
license = "GPL-3.0-or-later"

devices/expressive-e/osmose.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
},
164164
{
165165
"osc": "/general/sustain",
166+
"expects": "momentary",
166167
"cc": 64,
167168
"range": [
168169
0,
@@ -173,6 +174,7 @@
173174
},
174175
{
175176
"osc": "/general/sostenuto_1",
177+
"expects": "momentary",
176178
"cc": 66,
177179
"range": [
178180
0,
@@ -183,6 +185,7 @@
183185
},
184186
{
185187
"osc": "/general/sostenuto_2",
188+
"expects": "momentary",
186189
"cc": 69,
187190
"range": [
188191
0,

devices/moog/subsequent-37.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
},
9494
{
9595
"osc": "/oscillator_2/frequency_mode",
96+
"expects": "discrete",
9697
"nrpn_msb": 3,
9798
"nrpn_lsb": 103,
9899
"range": [
@@ -115,6 +116,7 @@
115116
},
116117
{
117118
"osc": "/oscillator_2/beat_mode",
119+
"expects": "switch",
118120
"nrpn_msb": 3,
119121
"nrpn_lsb": 104,
120122
"range": [
@@ -179,6 +181,7 @@
179181
},
180182
{
181183
"osc": "/mixer/oscillator_1_on",
184+
"expects": "switch",
182185
"nrpn_msb": 3,
183186
"nrpn_lsb": 106,
184187
"range": [
@@ -203,6 +206,7 @@
203206
},
204207
{
205208
"osc": "/mixer/sub_oscillator_on",
209+
"expects": "switch",
206210
"nrpn_msb": 3,
207211
"nrpn_lsb": 107,
208212
"range": [
@@ -227,6 +231,7 @@
227231
},
228232
{
229233
"osc": "/mixer/oscillator_2_on",
234+
"expects": "switch",
230235
"nrpn_msb": 3,
231236
"nrpn_lsb": 110,
232237
"range": [
@@ -251,6 +256,7 @@
251256
},
252257
{
253258
"osc": "/mixer/noise_on",
259+
"expects": "switch",
254260
"nrpn_msb": 3,
255261
"nrpn_lsb": 111,
256262
"range": [
@@ -275,6 +281,7 @@
275281
},
276282
{
277283
"osc": "/mixer/feedback_external_on",
284+
"expects": "switch",
278285
"nrpn_msb": 3,
279286
"nrpn_lsb": 114,
280287
"range": [
@@ -503,6 +510,7 @@
503510
},
504511
{
505512
"osc": "/filter_envelope/sync",
513+
"expects": "switch",
506514
"nrpn_msb": 4,
507515
"nrpn_lsb": 3,
508516
"range": [
@@ -515,6 +523,7 @@
515523
},
516524
{
517525
"osc": "/filter_envelope/loop",
526+
"expects": "switch",
518527
"nrpn_msb": 4,
519528
"nrpn_lsb": 4,
520529
"range": [
@@ -527,6 +536,7 @@
527536
},
528537
{
529538
"osc": "/filter_envelope/latch",
539+
"expects": "switch",
530540
"nrpn_msb": 4,
531541
"nrpn_lsb": 5,
532542
"range": [
@@ -539,6 +549,7 @@
539549
},
540550
{
541551
"osc": "/filter_envelope/clock_divider",
552+
"expects": "discrete",
542553
"nrpn_msb": 4,
543554
"nrpn_lsb": 6,
544555
"range": [
@@ -550,6 +561,7 @@
550561
},
551562
{
552563
"osc": "/filter_envelope/attack_exponential",
564+
"expects": "switch",
553565
"nrpn_msb": 4,
554566
"nrpn_lsb": 8,
555567
"range": [
@@ -746,6 +758,7 @@
746758
},
747759
{
748760
"osc": "/modulation_1/programmable_source",
761+
"expects": "discrete",
749762
"nrpn_msb": 3,
750763
"nrpn_lsb": 57,
751764
"range": [
@@ -757,6 +770,7 @@
757770
},
758771
{
759772
"osc": "/modulation_1/programmable_destination",
773+
"expects": "discrete",
760774
"nrpn_msb": 3,
761775
"nrpn_lsb": 59,
762776
"range": [
@@ -890,6 +904,7 @@
890904
},
891905
{
892906
"osc": "/modulation_2/programmable_source",
907+
"expects": "discrete",
893908
"nrpn_msb": 3,
894909
"nrpn_lsb": 82,
895910
"range": [
@@ -901,6 +916,7 @@
901916
},
902917
{
903918
"osc": "/modulation_2/programmable_destination",
919+
"expects": "discrete",
904920
"nrpn_msb": 3,
905921
"nrpn_lsb": 84,
906922
"range": [
@@ -969,6 +985,7 @@
969985
},
970986
{
971987
"osc": "/lfo_1/clock_divider",
988+
"expects": "discrete",
972989
"cc": 3,
973990
"range": [
974991
0,
@@ -995,6 +1012,7 @@
9951012
},
9961013
{
9971014
"osc": "/lfo_1/sync",
1015+
"expects": "switch",
9981016
"nrpn_msb": 3,
9991017
"nrpn_lsb": 41,
10001018
"range": [
@@ -1020,6 +1038,7 @@
10201038
},
10211039
{
10221040
"osc": "/lfo_1/clock_source",
1041+
"expects": "switch",
10231042
"nrpn_msb": 3,
10241043
"nrpn_lsb": 44,
10251044
"range": [
@@ -1055,6 +1074,7 @@
10551074
},
10561075
{
10571076
"osc": "/lfo_2/clock_divider",
1077+
"expects": "discrete",
10581078
"cc": 8,
10591079
"range": [
10601080
0,
@@ -1081,6 +1101,7 @@
10811101
},
10821102
{
10831103
"osc": "/lfo_2/sync",
1104+
"expects": "switch",
10841105
"nrpn_msb": 3,
10851106
"nrpn_lsb": 66,
10861107
"range": [
@@ -1106,6 +1127,7 @@
11061127
},
11071128
{
11081129
"osc": "/lfo_2/clock_source",
1130+
"expects": "switch",
11091131
"nrpn_msb": 3,
11101132
"nrpn_lsb": 69,
11111133
"range": [
@@ -1139,6 +1161,7 @@
11391161
},
11401162
{
11411163
"osc": "/arpeggiator/run",
1164+
"expects": "switch",
11421165
"nrpn_msb": 3,
11431166
"nrpn_lsb": 26,
11441167
"range": [
@@ -1175,6 +1198,7 @@
11751198
},
11761199
{
11771200
"osc": "/arpeggiator/sync",
1201+
"expects": "switch",
11781202
"nrpn_msb": 3,
11791203
"nrpn_lsb": 20,
11801204
"range": [
@@ -1187,6 +1211,7 @@
11871211
},
11881212
{
11891213
"osc": "/arpeggiator/range",
1214+
"expects": "discrete",
11901215
"nrpn_msb": 3,
11911216
"nrpn_lsb": 21,
11921217
"range": [
@@ -1198,6 +1223,7 @@
11981223
},
11991224
{
12001225
"osc": "/arpeggiator/back_forth",
1226+
"expects": "switch",
12011227
"nrpn_msb": 3,
12021228
"nrpn_lsb": 22,
12031229
"range": [
@@ -1210,6 +1236,7 @@
12101236
},
12111237
{
12121238
"osc": "/arpeggiator/back_forth_mode",
1239+
"expects": "switch",
12131240
"nrpn_msb": 3,
12141241
"nrpn_lsb": 23,
12151242
"range": [
@@ -1221,6 +1248,7 @@
12211248
},
12221249
{
12231250
"osc": "/arpeggiator/invert",
1251+
"expects": "switch",
12241252
"nrpn_msb": 3,
12251253
"nrpn_lsb": 24,
12261254
"range": [
@@ -1233,6 +1261,7 @@
12331261
},
12341262
{
12351263
"osc": "/arpeggiator/pattern",
1264+
"expects": "discrete",
12361265
"nrpn_msb": 3,
12371266
"nrpn_lsb": 25,
12381267
"range": [
@@ -1255,6 +1284,7 @@
12551284
},
12561285
{
12571286
"osc": "/arpeggiator/clock_divider",
1287+
"expects": "discrete",
12581288
"nrpn_msb": 3,
12591289
"nrpn_lsb": 29,
12601290
"range": [
@@ -1267,6 +1297,7 @@
12671297
},
12681298
{
12691299
"osc": "/arpeggiator/step_1_reset",
1300+
"expects": "trigger",
12701301
"nrpn_msb": 3,
12711302
"nrpn_lsb": 32,
12721303
"range": [
@@ -1303,6 +1334,7 @@
13031334
},
13041335
{
13051336
"osc": "/performance/pitch_bend_up_amount",
1337+
"expects": "discrete",
13061338
"cc": 107,
13071339
"range": [
13081340
0,
@@ -1314,6 +1346,7 @@
13141346
},
13151347
{
13161348
"osc": "/performance/pitch_bend_down_amount",
1349+
"expects": "discrete",
13171350
"cc": 108,
13181351
"range": [
13191352
0,
@@ -1390,6 +1423,7 @@
13901423
},
13911424
{
13921425
"osc": "/glide/gate",
1426+
"expects": "switch",
13931427
"nrpn_msb": 3,
13941428
"nrpn_lsb": 36,
13951429
"range": [
@@ -1402,6 +1436,7 @@
14021436
},
14031437
{
14041438
"osc": "/global/bank_select",
1439+
"expects": "discrete",
14051440
"cc": 0,
14061441
"range": [
14071442
0,
@@ -1412,6 +1447,7 @@
14121447
},
14131448
{
14141449
"osc": "/global/bank_select_lsb",
1450+
"expects": "discrete",
14151451
"cc": 32,
14161452
"range": [
14171453
0,
@@ -1467,6 +1503,7 @@
14671503
},
14681504
{
14691505
"osc": "/global/all_notes_off",
1506+
"expects": "trigger",
14701507
"cc": 123,
14711508
"range": [
14721509
0,

0 commit comments

Comments
 (0)