feat: checkpoint device agent runtime milestones

This commit is contained in:
2026-07-06 17:24:03 +08:00
parent 2d4251e98e
commit 5658735bca
153 changed files with 8060 additions and 65 deletions
@@ -0,0 +1,53 @@
## ADDED 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