Skip to content

Feature: derive supported plugins from the rig YAML (rig-aware plugin assist) #91

@mbreiser

Description

@mbreiser

Summary

Make the v3 Experiment Designer's plugin support rig-aware: read the rig YAML, derive the plugins that rig actually provides, and use that to drive the plugin UI and the cross-library import — surfacing the rig's supported plugins, binding to their canonical rig names, and flagging mismatches.

Update — builds on v0.20. v0.20 (4182168) already added an in-tool "+ Add plugin…" dropdown in Settings → Plugins, plus per-plugin remove. But it sources its list from the static registry (backlight, thermometer, camera) — it doesn't know what this rig supports or its config. This issue makes that existing dropdown rig-aware, and reuses the same onAddPlugin/docInsertPluginNode plumbing v0.20 introduced. It is no longer a from-scratch feature.

Is it feasible? Yes.

  • Rig YAMLs declare their plugins. Example (tests/fixtures/rigs/test_rig_1.yaml, copied verbatim from maDisplayTools):
    plugins:
      backlight:
        enabled: true
        type: "LED Controller"
        port: 'COM6'
      camera:
        enabled: true
        type: "Bias"
        ip: "127.0.0.1"
        port: 5010
        config_path: '...bias_config_default1.json'
      temperature:
        enabled: false
  • The editor already has a rig-file picker. In experiment_designer_v3.html, the Settings → Rig "Browse…" button (rigFile input, in renderSettings()) already opens a .yaml file and calls await file.text() — but currently keeps only the filename and discards the contents. We can parse those contents instead.
  • We already vendor a YAML parser (js/vendor/yaml/), used by parseV3Protocol.
  • The plugin registry maps rig hardware → protocol plugin classes. js/plugin-registry.js: backlightLEDControllerPlugin, cameraBiasPlugin, temperature/thermometerDAQThermometerPlugin, with findV3PluginByClass().
  • Adding plugins is already wired (v0.20). onAddPlugin() + docInsertPluginNode() insert a registry plugin today; this issue feeds them rig-derived options instead of the static list.

Test inputs (already in repo)

tests/fixtures/rigs/ — verbatim rigs from maDisplayTools: test_rig_1.yaml (enabled plugins + full config), example_rig.yaml (schema variation), test_rig_2.yaml (all disabled).

Browser constraint (by design)

Browsers can't read an arbitrary filesystem path, so the editor can't auto-open the rig from the rig: string alone. The user picks the file via the existing Browse… flow — same UX we already have.

Proposed behavior (layered on v0.20)

  1. When the user picks a rig file via Browse…, parse it and cache the rig's plugins: map (alongside the existing filename behavior).
  2. Make the v0.20 "+ Add plugin…" dropdown rig-aware: when a rig is loaded, offer its enabled plugins (with the right matlab.class) instead of (or marked apart from) the static registry list. Adding one binds to the canonical rig name (camera, not <prefix>__camera).
  3. Surface mismatches as soft warnings:
    • protocol references a plugin_name the rig doesn't support/enable, and
    • rig supports an enabled plugin the protocol never uses.
  4. Respect the rigDefined field convention — don't duplicate connection config (ip/port/paths) the rig owns.
  5. Non-destructive: assists, never silently rewrites the user's plugins:.

Mapping notes (the one real wrinkle)

Rig schemas drift — compare test_rig_1.yaml (type: "LED Controller", port) vs example_rig.yaml (no type, com_port, ir_power…), and camera type: "Bias" vs "BIAS". So the rig→class mapping must be tolerant: match the well-known rig key (backlight/camera/temperature) first, fall back to a normalized type, and degrade gracefully ("unknown plugin type") when unmapped.

Acceptance criteria

  • Picking a rig YAML via Browse… parses its plugins: block (tolerant across tests/fixtures/rigs/*).
  • The v0.20 "+ Add plugin…" dropdown reflects the loaded rig's enabled plugins, with their derived matlab.class; adding one uses the canonical rig name.
  • Mismatch warnings appear (protocol-uses-unsupported, rig-supports-unused), non-blocking.
  • Malformed/partial rig YAML degrades gracefully (clear message, no thrown module error).
  • Node tests cover rig-plugins parse + map against tests/fixtures/rigs/*.
  • No regression: npm test green; existing rig-path Browse/edit + v0.20 add/remove still work.

Pointers

  • experiment_designer_v3.html — Settings → Rig Browse handler (rigFile); the v0.20 Plugins section + onAddPlugin/onRemovePlugin.
  • js/plugin-registry.jsfindV3PluginByClass(), BUILTIN_PLUGINS, rigDefined.
  • js/protocol-yaml-v3.jsdocInsertPluginNode(), docRemovePlugin().
  • tests/fixtures/rigs/ — rig inputs (+ its README). Vendored parser: js/vendor/yaml/.

Open questions

  • Bulk "Add all enabled rig plugins" vs per-plugin only?
  • When a rig plugin's config differs from an already-declared protocol plugin, reconcile/flag, or leave the protocol authoritative?
  • Rig→class mapping as a small table in plugin-registry.js (preferred) vs inferred purely from the rig key?

Related: #89 — imported plugins get a filename prefix and break rig binding

#89 is the bug this would fully close. D4 cross-library import namespaces an imported camera plugin to <prefix>__camera. Plugin names in the experiment YAML must match the rig YAML's names (camera/backlight/temperature) to inherit the rig's config, so the prefixed name fails at runtime.

Shared root cause: the rig defines the canonical plugin names, and the editor doesn't know them. D4 only avoids prefixing when it can merge with a plugin the target protocol already declares (same class + config); when the target hasn't declared camera yet, it falls back to namespacing → the broken name.

Note (post-v0.20): v0.20's add-plugin dropdown resolves the "I couldn't find a way to add the camera" half of #89 — you can now add camera in-tool with its canonical name. The remaining actionable part of #89 is strictly the D4 import path still prefixing plugin names.

Why they're better together

Reading the rig's plugins (this issue) gives the import step the missing fact: if a to-be-imported plugin maps to one the rig supports, bind to the rig-canonical name instead of prefixing — even when the target protocol doesn't declare it yet. #91 is the enabler; #89 is one of its payoffs.

Combined scope

  1. Land rig-plugin parsing + tolerant mapping (substrate).
  2. D4 import's plugin step consults it: never prefix a rig-supported (or built-in) plugin name — bind to the canonical rig name. Closes Plugins imported from another yaml have incorrect name when exported #89.
  3. Acceptance: importing a camera condition into a camera-less protocol exports plugin_name: "camera" (not <prefix>__camera) whenever the rig supports camera.

Fallback if #91 slips: #89 can be fixed narrowly on its own — treat the well-known names (camera/backlight/temperature) as canonical and never prefix them, no rig parsing required. The rig-aware approach here is the correct general solution; the narrow fix is a viable stopgap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions