# plugin-system Specification ## Purpose TBD - created by archiving change cloud-runtime. Update Purpose after archive. ## Requirements ### Requirement: Plugin manifest schema The system SHALL define a `PluginManifest` schema with a unique `name`, a `version`, an `entry_point_kind` restricted to `driver`, `tool`, or `skill`, and a `target` (a dotted module:attribute reference to the plugin's implementation), and SHALL reject a manifest missing any required field or using an unrecognized `entry_point_kind`. #### Scenario: Valid manifest accepted - **WHEN** a manifest with all required fields and a recognized `entry_point_kind` is submitted for registration - **THEN** the registry accepts it and stores it as a known plugin #### Scenario: Manifest with unrecognized entry_point_kind rejected - **WHEN** a manifest declares an `entry_point_kind` other than `driver`, `tool`, or `skill` - **THEN** the registry rejects it with a clear validation error and does not register it #### Scenario: Duplicate plugin name rejected - **WHEN** a manifest is submitted whose `name` matches an already-registered plugin - **THEN** the registry rejects the new registration with a clear conflict error rather than silently overwriting the existing entry ### Requirement: Plugin discovery via entry points and manifest files The system SHALL discover plugin manifests both from installed Python packages declaring an entry point in the `device_agent_runtime.plugins` group and from local `plugin.json` files under a configured scan path, feeding both sources into the same validation-and-registration path. #### Scenario: Discovery via installed entry point - **WHEN** an installed package declares an entry point in the `device_agent_runtime.plugins` group resolving to a valid manifest - **THEN** `PluginRegistry.discover()` finds and registers it #### Scenario: Discovery via local manifest file - **WHEN** a `plugin.json` file exists under the configured plugin scan path and parses into a valid manifest - **THEN** `PluginRegistry.discover()` finds and registers it #### Scenario: Malformed manifest file is skipped, not fatal - **WHEN** a `plugin.json` file under the scan path fails to parse or fails schema validation - **THEN** `PluginRegistry.discover()` skips that file, records it as a discovery error, and continues discovering remaining plugins rather than aborting the whole scan ### Requirement: Driver-kind plugins register into the driver registry extension point The system SHALL, for a manifest with `entry_point_kind == "driver"`, resolve its `target` to a driver-factory builder and register it under the manifest's `name` as a new `driver_type` in the existing driver-registry extension point, without requiring any edit to the `driver` package's own files. #### Scenario: Driver plugin registered successfully - **WHEN** a valid `driver`-kind manifest is registered and its `target` resolves to a callable driver-factory builder - **THEN** the manifest's `name` becomes usable as a `driver_type` value by any caller building a driver factory, with no change to existing driver-registry code #### Scenario: Driver registry extension point unavailable - **WHEN** a `driver`-kind manifest is registered but the driver-registry's registration function is not importable in the running environment - **THEN** the registry raises a clear, explicit error naming the missing integration point, rather than silently accepting the manifest without wiring it ### Requirement: Tool and skill plugin manifests are accepted but explicitly marked unwired The system SHALL accept and store `tool`- and `skill`-kind plugin manifests (listable like any other registered plugin) but SHALL report them as not wired to any execution path, rather than implying they are active. #### Scenario: Tool-kind manifest registered - **WHEN** a valid `tool`-kind manifest is registered - **THEN** the registry stores it and it appears in a plugin listing with a `wired: false` indicator, and no tool dispatch path is modified as a result #### Scenario: Skill-kind manifest registered - **WHEN** a valid `skill`-kind manifest is registered - **THEN** the registry stores it and it appears in a plugin listing with a `wired: false` indicator, and no skill store or execution path is modified as a result