7.8 KiB
Capability-Oriented Module Orchestration
- Summary
- Background
- Context
- Goals
- Non-goals
- Proposal
- Vision
- Design Details
- Lifecycle Model
- Capability Registry Model
- Use Cases
- Verify & Test
- Criteria
- Test & QA
- Progress
- Status
- Next Steps
- Reviews
- Q&A
- Related Documentations
Summary
Define a capability-oriented orchestration model for AIRI plugins and modules where dependency resolution is runtime-driven instead of static metadata-driven. Plugin Host coordinates module lifecycle using a stateful capability registry and readiness gates, enabling multi-runtime deployments (Electron, Web, Pocket) without hardcoding stage-first boot order.
Background
Current plugin lifecycle in PluginHost is phase-based but does not yet enforce dynamic dependency waiting between modules and platform-provided APIs. In practice, APIs like provider listing can be available only after platform runtime, stage runtime, and UI/store initialization complete. This creates race conditions when modules initialize before required capabilities are actually ready.
Context
The AIRI ecosystem is moving toward:
- Multiple plugin hosts (Electron now, Pocket and Web later).
- Multiple stage instances per host/runtime.
- Platform-specific extension APIs that should be discoverable through one control-plane model.
- Plugin modules that may provide capabilities required by other modules and by stage/configurator flows.
The design must avoid privileged hardcoded ordering such as "stage always loads first", while still giving deterministic and testable startup behavior.
Goals
- Support runtime capability discovery and readiness gating without static dependency metadata.
- Keep lifecycle orchestration host-driven and runtime-neutral.
- Allow module dependencies to target capabilities, not implementation modules.
- Support multiple stage instances and platform-specific APIs in one model.
- Prevent missed readiness signals by relying on stateful registry snapshots, not one-shot events.
Non-goals
- Defining the final production policy engine (priority, quotas, fairness) in this iteration.
- Designing UI/UX details of configurator pages.
- Finalizing transport federation protocol between all runtimes in this document.
Proposal
Introduce a host-owned capability registry and make module initialization capability-aware:
- Modules announce possible capabilities early (
announced/preparingphase). - Modules mark capabilities as ready once invokable.
- Modules declare runtime requirements as capability predicates.
- Host transitions modules into
waiting-depsuntil requirements resolve. - Host resumes module preparation/setup when required capabilities become ready.
Readiness and availability are stateful in registry snapshots, with event notifications as incremental updates.
Vision
AIRI plugin orchestration should behave like an extensible runtime kernel:
- Hosts are runtime adapters (Electron, Pocket, Web), not policy exceptions.
- Stages are normal modules that publish and consume capabilities.
- Modules compose through capability contracts, not hardcoded start order.
- Adding new platform APIs means registering new capabilities, not rewriting lifecycle code.
Design Details
Capability-first lifecycle orchestration with dynamic dependency resolution.
Lifecycle Model
Proposed host-side phases for each module:
loadingloadedauthenticatingauthenticatedannouncedpreparingwaiting-depspreparedconfiguration-neededconfiguredreadydegradedfailedstopped
Key rules:
preparing -> waiting-depsif required capabilities are unresolved.waiting-deps -> preparedwhen all required capability predicates resolve.ready -> degradedwhen previously bound capability is withdrawn/degraded.degraded -> readywhen dependency set becomes healthy again.
Capability Registry Model
Registry properties:
- Stateful snapshot store (authoritative readiness state).
- Capability records scoped by
hostId,instanceId, and runtime. - Support both direct key lookup and predicate matching.
- Version and health metadata per capability record.
Capability record baseline:
interface CapabilityRecord {
capabilityId: string
providerModuleId: string
hostId: string
instanceId?: string
runtime: 'electron' | 'web' | 'pocket' | 'node'
state: 'announced' | 'ready' | 'degraded' | 'withdrawn'
version?: string
health?: 'ok' | 'degraded' | 'unknown'
metadata?: Record<string, unknown>
}
Requirement baseline:
interface CapabilityRequirement {
allOf?: string[]
anyOf?: string[]
predicate?: (record: CapabilityRecord) => boolean
timeoutMs?: number
}
Use Cases
-
Stage provider catalog dependency chain
- Provider-definition plugin announces capability.
- Stage/configurator module announces provider catalog capability when store is mounted.
- Consumer plugin module waits for both capabilities, then configures provider-backed features.
-
Multi-stage instance isolation
- Two stage instances in one host register same capability class under different
instanceId. - Module requests capability in same
instanceIdscope. - Host binds consumer to correct stage-local capability.
- Two stage instances in one host register same capability class under different
-
Pocket runtime API extension
- Pocket runtime module registers
mobile.sensorcapability. - Plugins targeting mobile predicates can activate on pocket host without Electron-specific assumptions.
- Pocket runtime module registers
-
Late readiness and replay safety
- Capability became ready before module started waiting.
- Module receives snapshot-based resolution immediately and skips unnecessary wait.
Verify & Test
Criteria
- Module lifecycle correctly enters
waiting-depswhen required capabilities are missing. - Module resumes deterministically when capabilities become ready.
- Snapshot-based registry prevents missed-ready race conditions.
- Same module capability requirements work across Electron and at least one non-Electron runtime adapter.
- Capability scoping by
instanceIdprevents cross-stage binding errors.
Test & QA
- Unit test: registry stores and replays announced/ready/degraded states.
- Unit test: module transitions
preparing -> waiting-deps -> prepared. - Unit test: pre-existing ready capability resolves wait immediately.
- Unit test: degraded dependency transitions module from
readytodegraded. - Integration test: stage-side capability registration unblocks plugin module initialization.
Progress
Status
Proposed.
Next Steps
- Add host registry abstraction and lifecycle integration in
packages/plugin-sdk/src/plugin-host. - Introduce
waiting-depsanddegradedtransitions to host state machine and tests. - Define minimal protocol events for capability announce/ready/degraded/snapshot.
- Wire stage-side capability publication in Electron host integration first.
Reviews
Q&A
-
Q: Why not use static plugin dependency metadata? A: Runtime capability dependencies are more flexible for multi-stage and multi-runtime setups where availability depends on live initialization state, not package declarations.
-
Q: How does this avoid missed readiness events? A: Registry snapshot is authoritative. Events are incremental signals only; late consumers always query snapshot state.
-
Q: Does this force one core stage ordering? A: No. Ordering emerges from capability availability and requirement predicates, not privileged host rules.