Plugin lifecycle¶
A plugin moves through discovery, command construction, context resolution, and execution. Each stage is delayed until it is needed.
1. Discovery¶
The root Click group queries installed metadata for the
transpiler_mate.plugins entry-point group. It sorts commands by name and
detects duplicate registrations without importing plugin modules.
This keeps root help responsive and prevents one unused plugin's import cost from affecting every invocation.
2. Loading and command construction¶
When a command is requested, its entry point is loaded and checked against the
TranspilerPlugin protocol. The entry-point name and plugin name must agree.
The runtime then reads plugin.options_model.model_fields and combines the
derived plugin options with the common SOURCE argument and connection
options. The generated command is cached.
3. Option validation¶
Click parses individual values. The runtime omits untouched, non-required defaults from the input dictionary so Pydantic can run default factories and model-level logic normally. It then validates the complete options model with both aliases and Python field names enabled.
No source is loaded when showing plugin help or when option validation fails.
4. Context resolution¶
Only immediately before execution does the command create a resolver. The resolver mounts transport adapters, loads the CWL document, validates its Schema.org metadata, and optionally selects a process.
The resulting TranspilerContext gives every plugin the same normalized view
of its input regardless of whether the source was a local path, HTTP URL, or
OCI location.
5. Execution and reporting¶
The runtime calls plugin.execute(context, options). It distinguishes expected
result failures from unexpected execution errors, logs a success or failure
banner, and always reports elapsed and finish times once execution has begun.