Plugin Architecture¶
The FCC framework provides a plugin system with 10 plugin types, entry-point discovery via importlib.metadata, a central PluginRegistry, and a CrossPluginOrchestrator for dependency resolution and interaction management across the ecosystem.
flowchart TD
EP[setuptools entry points] --> PR[PluginRegistry]
PR --> |discover| D{10 Plugin Types}
D --> P1[PersonaPlugin]
D --> P2[EnginePlugin]
D --> P3[TemplatePlugin]
D --> P4[ScorerPlugin]
D --> P5[ValidatorPlugin]
D --> P6[ProviderPlugin]
D --> P7[GovernancePlugin]
D --> P8[ScenarioPlugin]
D --> P9[WorkflowPlugin]
D --> P10[EventSubscriberPlugin]
PR --> CPO[CrossPluginOrchestrator]
CPO --> Health[EcosystemHealthReport]
Plugin Types¶
Each plugin type corresponds to a setuptools entry-point group under fcc.plugins.*:
| Plugin Type | Entry-Point Group | Purpose | ABC |
|---|---|---|---|
| Personas | fcc.plugins.personas |
Contribute additional persona YAML definitions | PersonaPlugin |
| Engines | fcc.plugins.engines |
Provide custom simulation engines | EnginePlugin |
| Templates | fcc.plugins.templates |
Supply Jinja2 doc templates | TemplatePlugin |
| Scorers | fcc.plugins.scorers |
Implement custom quality scoring | ScorerPlugin |
| Validators | fcc.plugins.validators |
Add custom validation rules | ValidatorPlugin |
| Providers | fcc.plugins.providers |
Provide data or AI services | ProviderPlugin |
| Governance | fcc.plugins.governance |
Extend governance frameworks | GovernancePlugin |
| Scenarios | fcc.plugins.scenarios |
Contribute simulation scenarios | ScenarioPlugin |
| Workflows | fcc.plugins.workflows |
Add custom workflow graphs | WorkflowPlugin |
| Subscribers | fcc.plugins.subscribers |
Register event bus subscribers | EventSubscriberPlugin |
PluginMeta¶
Every plugin exposes metadata through the plugin_meta() method, returning a frozen PluginMeta dataclass:
| Field | Type | Description |
|---|---|---|
id |
str |
Unique plugin identifier |
name |
str |
Human-readable plugin name |
version |
str |
Semantic version string |
plugin_type |
PluginType |
One of the 10 plugin types |
description |
str |
Plugin description |
author |
str |
Plugin author |
source_package |
str |
Python package providing this plugin |
tags |
tuple[str, ...] |
Categorization tags |
Plugin ABCs¶
Each plugin type has an abstract base class defining its contract. Here are the key ABCs:
PersonaPlugin¶
class PersonaPlugin(ABC):
@abstractmethod
def plugin_meta(self) -> PluginMeta: ...
@abstractmethod
def get_persona_paths(self) -> list[Path]:
"""Return paths to YAML files containing persona definitions."""
def get_dimension_paths(self) -> list[Path]:
"""Return paths to dimension profile YAML files (optional)."""
return []
def get_cross_reference_paths(self) -> list[Path]:
"""Return paths to cross-reference YAML files (optional)."""
return []
EnginePlugin¶
Contributes a custom simulation engine class that the framework can use in place of the default engine.
EventSubscriberPlugin¶
The 10th plugin type, connecting the plugin system with the event bus. Subscriber plugins register callbacks for specific event types during framework initialization.
PluginRegistry¶
The PluginRegistry is the central registry for discovering, loading, and accessing plugins.
Discovery¶
from fcc.plugins.registry import PluginRegistry
registry = PluginRegistry()
result = registry.discover()
print(result.discovered) # Total entry points found
print(result.loaded) # Successfully loaded
print(result.errors) # List of error messages
Discovery scans all fcc.plugins.* entry-point groups using importlib.metadata.entry_points(). Each entry point is loaded, instantiated, and validated against the appropriate ABC. Plugins that fail to load are recorded as errors but do not block other plugins.
Querying Plugins¶
from fcc.plugins.base import PluginType
# Get all plugins of a specific type
persona_plugins = registry.get_plugins(PluginType.PERSONAS)
# Get a specific plugin by ID
plugin = registry.get_plugin("paom-personas")
# Check if a plugin exists
exists = registry.has_plugin("paom-personas")
Entry-Point Registration¶
Plugins register through pyproject.toml or setup.cfg:
[project.entry-points."fcc.plugins.personas"]
my-personas = "my_package.fcc_plugin:MyPersonaPlugin"
[project.entry-points."fcc.plugins.subscribers"]
my-subscriber = "my_package.fcc_plugin:MySubscriberPlugin"
CrossPluginOrchestrator¶
The CrossPluginOrchestrator manages interactions between ecosystem plugins, providing dependency resolution, interaction matrix querying, and health monitoring.
Dependencies¶
from fcc.plugins.orchestration import CrossPluginOrchestrator, PluginDependency
orchestrator = CrossPluginOrchestrator()
# Add a dependency
orchestrator.add_dependency(PluginDependency(
source_plugin="constel",
target_plugin="paom",
dependency_type="provides_taxonomy",
description="CONSTEL provides taxonomy data to PAOM",
))
# Resolve dependencies for a plugin
deps = orchestrator.resolve_dependencies("constel")
# Find reverse dependencies (who depends on this plugin?)
rdeps = orchestrator.reverse_dependencies("paom")
Interactions¶
Cross-plugin persona interactions track how personas from different plugins collaborate:
from fcc.plugins.orchestration import PluginInteraction
orchestrator.add_interaction(PluginInteraction(
source_persona="STE",
source_plugin="fcc-core",
target_persona="OA",
target_plugin="constel",
interaction_type="peer",
description="Taxonomy alignment between STE and OA",
))
# Query interaction matrix grouped by source plugin
matrix = orchestrator.get_interaction_matrix()
# Get all interactions for a specific persona
interactions = orchestrator.get_interactions_for_persona("STE")
# Validate all interactions reference known plugins
errors = orchestrator.validate_interactions()
Ecosystem Health¶
from fcc.plugins.orchestration import PluginHealthStatus
statuses = [
PluginHealthStatus(plugin_id="fcc-core", healthy=True, persona_count=24),
PluginHealthStatus(plugin_id="paom", healthy=True, persona_count=30),
PluginHealthStatus(plugin_id="constel", healthy=False, error="Missing dep"),
]
report = orchestrator.check_health(statuses)
print(report.total_plugins) # 3
print(report.healthy_plugins) # 2
print(report.unhealthy_plugins) # 1
print(report.total_personas) # 54
Data Files¶
Plugin ecosystem configuration is stored in src/fcc/data/ecosystem/:
plugin_dependencies.yaml-- Declares inter-plugin dependencies with types and descriptionsplugin_interactions.yaml-- Maps cross-plugin persona interactions with directions
Error Handling¶
The plugin system defines three specific error types in fcc.plugins.errors:
| Error | When Raised |
|---|---|
PluginLoadError |
Plugin fails to load or instantiate |
PluginConflictError |
Two plugins register the same ID |
PluginNotFoundError |
Requested plugin ID does not exist |