Skip to content

Chain floor 1, the host verb table, and the union-world requirement for LV2 chains (#131) - #133

Merged
linuxnow merged 5 commits into
mainfrom
cluster/plugin-hostd-131-local
Oct 22, 2026
Merged

linuxnow merged 5 commits into
mainfrom
cluster/plugin-hostd-131-local

Conversation

@linuxnow

@linuxnow linuxnow commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Part of #131. Three of its parts, in small commits; the Zynthian gap verbs (preset save/show/load on the CLAP worker, parameter feedback, MIDI learn) and the union-narrowed world itself are a follow-up on #131, not here.

Chain floor 1 (8a10634). chain_members_min (1) is a declared constant, with line_words_max (64), the word count verbs.c reads a line to. The grammar in verbs.c and the supervisor's own guard both read the floor from the header, so a chain of one runs in a worker of its own; a chain of none stays outside the grammar (-902). a_chain_of_one_runs_in_a_worker_of_its_own_and_a_chain_of_none_is_refused asserts both answers, the chain_formed 5 <worker> 21 event, the worker told chain 5 21, the member's parameter kept, and chain_clear giving it back a worker of its own. Three sabotage arms put the floor of two back in the header, the grammar and the supervisor; each turns it red.

The host verb table (d11f368, 30a1c7a). PHD_HOST_VERBS in protocol.h gives every verb a controller sends the daemon a level (required, optional, absent) for four profiles: lv2-worker, clap-worker, console, zynthian. The mod-ui rows carry the ruled starting values, with MIDI learn and CV addressing required of the CLAP worker and of Zynthian (ruling of 2026-10-22). protocol-gen writes the table into protocol/plugin-hostd.json (host_profiles, host_verbs, both in the schema) and into the README. tests/verb_table.py (make check-verb-table, in make test) builds a program against the header and holds the table to mod-host.json's commands, PHD_VERBS and PHD_INSTANCE_VERBS: a verb with no row, a row twice, a row for a verb nothing declares that is not absent everywhere, and a verb the daemon answers itself that is not required of every profile each fail. Four sabotage arms (a row dropped, a verb added to PHD_VERBS with no row, chain made absent for the console, a verb mod-host never had made required) each go red.

For review: the 34 rows outside the 35 mod-ui verbs are this tree's proposal, not a ruling. Daemon verbs are required everywhere (the daemon answers them whatever the worker); disconnect, set_bpm, set_bpb and quit are required; the other mod-host commands and the instance verbs are optional.

LV2 chains under require_pins (b31be14, ec835c5). The chain note now states the union-narrowed world as required, where it had an open question, and records the -101 that a chain member gave in a single-bundle LV2_PATH in omx-clap-core's Stage 0 bench. The chain verb's -501 clause says that every LV2 plugin, a chain of one included, is refused while require_pins is on, until a chain's worker gets the union of its members' bundles. under_require_pins_a_chain_of_lv2_members_is_refused_until_its_worker_gets_the_union_of_their_bundles holds that refusal for a chain of one and of two pinned LV2 members: nothing moves and no worker is told. A sabotage arm that drops the guard turns it red. narrow_world still takes one uri, so the union is not built here.

Run in a Fedora 44 container (mod-host-protocol-devel 0.10.6, omx-contract-devel 3.0.0, no network), after make clean and a build: make test green, including plugin-hostd tests ok (0 failed), generated files are current, the schema check, the C consumer, the verb table and the verbs contract. make private-refs was green on the host. python3 tests/sabotage.py in full: 225 arms caught, 6 skipped (no OMX_CLAP_HOST), and 1 survived, "worker_env is not applied to a running worker". Run alone three times on this branch, that arm went red each time, and it also goes red on main. It looks like a timing flake under the load of the full run, not something this branch changed, but that is not proven.

Not run: the jack, lv2 and real-worker tiers (test-jack, test-lv2-adapter), which need JACK and the real workers. The README half of the verbs contract was skipped because no mod-host checkout was present. No bench was run.

chain_members_min (1) joins the declared constants with line_words_max
(64), the word count verbs.c reads a line to. The grammar in verbs.c and
the supervisor's own guard both read the floor from the declaration, so a
chain of one runs in a worker of its own and a chain of none is still
outside the grammar (-902). A daemon test asserts both answers, and three
sabotage arms put the old floor of two back in the header, the grammar
and the supervisor, each turning it red.
…#131)

PHD_HOST_VERBS declares, for every verb a controller sends the daemon,
whether the lv2-worker, clap-worker, console and zynthian profiles
require it, may answer it, or leave it absent on purpose. The mod-ui
rows carry the ruled starting values, with MIDI learn and CV addressing
required of the CLAP worker and of Zynthian; the mod-host and daemon
rows are this tree's. protocol-gen writes the table into
protocol/plugin-hostd.json (host_profiles, host_verbs, in the schema)
and into the README.

tests/verb_table.py (make check-verb-table, part of make test) builds a
program against the header and holds the table to mod-host.json's
commands, PHD_VERBS and PHD_INSTANCE_VERBS: a verb with no row, a row
twice, a row for a verb nothing declares that is not absent everywhere,
and a verb the daemon answers itself that is not required of every
profile each fail. Four sabotage arms break the table those ways and go
red.
verbs_contract.py reads every PHD_VERB_ string of the header as a verb,
so PHD_VERB_SOURCE_DAEMON made "daemon" one and would have refused that
word in any C string of the sources. The sources are
PHD_HOST_VERB_SOURCE_*; the contract counts 40 verbs and events again.
)

The chain note states the requirement where it had an open question: a
chain's worker gets a world narrowed to the union of its members'
bundles, so each LV2 pin still holds, and a member whose bundle is not
found leaves the chain unformed. It records the failure the union fixes
(a chain member in a single-bundle LV2_PATH answered -101 in
omx-clap-core's Stage 0 bench) and that a chain of one LV2 member is
refused too today, its worker being a chain's and not an own one.

The chain verb's -501 clause says so, and a daemon test holds the
refusal for a chain of one and of two pinned LV2 members, nothing moved
and no worker told; a sabotage arm that drops the guard turns it red.
The union itself is not built here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant