API: Pipeline Package

The pipeline package exposes construction, planning, execution, runtime policy, configuration versioning, and asynchronous runner contracts.

Execution Facades

Pipeline

Public execution facade for a single pipeline run.

Pipeline intentionally coordinates collaborators instead of owning the workflow details. Frame execution, signal analysis, visualization, event injection, and output assembly are delegated to focused collaborators in this package. This keeps the public API stable while avoiding a god object.

Responsibilities
  • Validate no business rule directly; validation belongs to PipelineContext and the concrete components.
  • Build a stable execution plan before the run starts.
  • Keep execution-mode decisions behind PipelineExecutionPolicy.
  • Inject runtime event metadata into event-aware components.
  • Delegate execution to SegmentedPipelineExecutor.
  • Convert the internal execution result into public PipelineOutputs.
Extension notes

New execution behavior should normally be introduced through a custom PipelineExecutionPolicy or through segmented runtime collaborators rather than by adding stage logic here. This class should remain thin so callers can treat it as a stable facade.

__init__

__init__(
    context: PipelineContext,
    event_bus: IEventBus | None = None,
    pipeline_id: str | None = None,
    execution_metadata: Mapping[str, Any] | None = None,
    execution_policy: PipelineExecutionPolicy | None = None,
) -> None

Create a pipeline facade for an already-built context.

Parameters:

Name Type Description Default
context PipelineContext

Immutable set of pipeline components and runtime configuration.

required
event_bus IEventBus | None

Optional domain event bus injected into components implementing IEventEmitter.

None
pipeline_id str | None

Optional stable identifier propagated into metadata and artifacts.

None
execution_metadata Mapping[str, Any] | None

Additional metadata copied into event contexts, visualizer contexts, exporter contexts, and final run metadata.

None
execution_policy PipelineExecutionPolicy | None

Optional strategy used by planner and runtime to choose batch or streaming execution for each stage.

None

run

run() -> PipelineOutputs

Execute the pipeline and return analyzer results plus artifacts.

Returns:

Type Description
PipelineOutputs

Final analyzer results, visual artifacts, debug artifacts, execution metadata, execution plan, and reproducibility exports.

Raises:

Type Description
PipelineExecutionError

If any stage delegated to a component fails.

execution_plan

execution_plan() -> PipelineExecutionPlan

Return the adaptive execution plan that will be used by run.

The plan is computed once during construction so callers can inspect streaming decisions and materialization boundaries before execution.

PipelineOrchestrator

Application-facing pipeline execution facade.

The orchestrator is the single public access point for execution: synchronous runs go through run(context), background runs go through submit(context), and event-driven integrations are optional adapters around the same submit path.

Boundary

The orchestrator coordinates application ports. It does not validate component schemas or execute stage logic directly; those responsibilities belong to builders, contexts, runners, and pipeline execution collaborators.

run

run(
    context: PipelineContext,
    pipeline_id: str | None = None,
    execution_metadata: Mapping[str, Any] | None = None,
) -> PipelineOutputs

Execute a pipeline synchronously and return analyzer results.

This path does not require an EventBus. If a domain bus was configured, it is injected into event-emitting components before execution.

Parameters:

Name Type Description Default
context PipelineContext

Validated pipeline context.

required
pipeline_id str | None

Optional run id. A unique id is generated when omitted.

None
execution_metadata Mapping[str, Any] | None

Optional metadata propagated into pipeline events, visualizer contexts, output metadata, and reproducibility data.

None

Returns:

Type Description
PipelineOutputs

Completed outputs for the run.

submit

submit(
    context: PipelineContext,
    pipeline_id: str | None = None,
    execution_metadata: Mapping[str, Any] | None = None,
) -> Future[PipelineOutputs]

Submit a pipeline for background execution.

Returns:

Type Description
Future[PipelineOutputs]

Future owned by the configured runner.

terminate

terminate(pipeline_id: str) -> bool

Best-effort cancellation for a queued async pipeline.

Parameters:

Name Type Description Default
pipeline_id str

Run identifier returned or supplied at submission time.

required

Returns:

Type Description
bool

True only when the underlying runner cancelled queued work that had not started yet. Already-running pipelines are not interrupted.

active_ids

active_ids() -> list[str]

Return a snapshot of currently active pipeline ids.

This list is a snapshot of the pipelines currently being executed. It does not imply that the pipelines are still running at the time of calling this method because async runs may complete immediately after the snapshot is read.

shutdown

shutdown(wait: bool = True) -> None

Shut down the underlying runner.

Parameters:

Name Type Description Default
wait bool

When True, block until running pipelines finish. When False, ask the runner to cancel pending work and return without waiting for already-running pipelines.

True

ThreadedPipelineRunner

Bases: IPipelineRunner

Execute pipelines on a ThreadPoolExecutor.

run() and submit() share active-id tracking: the same pipeline id cannot be executed concurrently through either entry point. submit() returns the underlying Future so callers can observe asynchronous results or failures.

cancel() is best-effort: it can cancel queued work that has not started, but it cannot interrupt a pipeline that is already running.

Lifecycle events are dispatched synchronously to the configured IEventBus from within the worker thread.

Thread safety

Runner bookkeeping is protected by a lock. Component instances inside a submitted Pipeline remain responsible for their own thread-safety.

run

run(
    pipeline_id: str, pipeline: Pipeline
) -> PipelineOutputs

Execute a pipeline synchronously through the retry/lifecycle path.

Raises:

Type Description
PipelineRunAlreadyActiveError

If another run with the same id is active or queued.

PipelineExecutionError

If execution fails and retry policy declines another attempt.

submit

submit(
    pipeline_id: str, pipeline: Pipeline
) -> Future[PipelineOutputs]

Submit a pipeline for background execution.

Parameters:

Name Type Description Default
pipeline_id str

Stable run identifier used by monitor, output store, and lifecycle events.

required
pipeline Pipeline

Already-built pipeline facade.

required

Returns:

Type Description
Future[PipelineOutputs]

Future that resolves to completed pipeline outputs or raises the execution failure.

Raises:

Type Description
PipelineRunAlreadyActiveError

If another run with the same id is active or queued.

Exception

Any monitor or executor failure raised while reserving the run id.

cancel

cancel(pipeline_id: str) -> bool

Cancel queued work for a pipeline id when possible.

Returns:

Type Description
bool

True only when the underlying Future accepted cancellation. Already-running pipelines cannot be interrupted through this method.

active_ids

active_ids() -> list[str]

Return the monitor-backed snapshot of active pipeline ids.

snapshot

snapshot(pipeline_id: str) -> PipelineRunSnapshot | None

Return the latest known state for a pipeline id.

snapshots

snapshots() -> list[PipelineRunSnapshot]

Return latest known state for all tracked pipeline ids.

shutdown

shutdown(wait: bool = True) -> None

Shut down the executor.

With wait=False pending tasks are cancelled best-effort. Running pipelines are not interrupted and clean themselves up through _finish.

Context and Builders

PipelineContext dataclass

Immutable dependency graph for one pipeline execution unit.

Design rationale

PipelineContext owns construction invariants, not execution logic. It is a frozen value assembled by builders or factories before execution starts. Pipeline can therefore remain a thin facade over planning and runtime collaborators, while tests and application services can inspect a complete pipeline topology without running it.

Lifecycle

A context is normally built once per submitted run. It may be reused when all contained component instances are themselves safe to reuse; components with per-run mutable state should be instantiated per run by the builder or registry factory.

Thread safety

The context normalizes component collections to tuples and deep-copies source_config. It does not make contained component objects immutable or thread-safe.

Attributes:

Name Type Description
frame_extractor IFrameExtractor

Required source component that produces frames.

signal_extractor ISignalExtractor

Required component that turns processed frames into signal samples.

analyzers Sequence[IAnalyzer]

Non-empty analyzer sequence.

frame_processors Sequence[IFrameBufferProcessor]

Optional buffer-level preprocessing steps.

frame_exporters Sequence[IFrameExporter]

Optional final-output exporters that consume processed frames and return artifacts while preserving replayable frames.

signal_cleaners Sequence[ISignalCleaner]

Optional signal smoothing, filtering, or normalization steps.

visualizers Sequence[IVisualizer]

Visualizers applied to all analyzer results.

visualizer_bindings Sequence[VisualizerBinding]

Selective visualizer-to-result bindings.

intermediate_frame_capture IntermediateFrameCaptureConfig

Bounded capture policy for frame-processing debug snapshots.

intermediate_frame_visualizers Sequence[IVisualizer]

Visualizers dedicated to intermediate frame collections.

stream_runtime StreamRuntimeConfig

Bounded-buffer and latency-policy settings used by adaptive streaming.

source_config Mapping[str, Any]

Compact construction metadata for reproducibility exports.

Raises:

Type Description
PipelineContextError

If required components are missing, required sequences are empty, or a typed field receives an invalid object.

FluentPipelineBuilder

Programmatic builder for PipelineContext.

The builder only collects pipeline components and creates a validated context. Execution belongs to Pipeline, PipelineOrchestrator, or a custom runner.

Mutability

The builder is mutable and intended for single-threaded setup code. Calling build_context() returns an immutable PipelineContext.

with_frame_extractor

with_frame_extractor(
    extractor: IFrameExtractor,
) -> FluentPipelineBuilder

Replace the required frame extractor and return this builder.

with_signal_extractor

with_signal_extractor(
    extractor: ISignalExtractor,
) -> FluentPipelineBuilder

Replace the required signal extractor and return this builder.

with_frame_processors

with_frame_processors(
    processors: Iterable[IFrameBufferProcessor],
) -> FluentPipelineBuilder

Replace buffer-level frame processors and return this builder.

add_frame_processor

add_frame_processor(
    processor: IFrameBufferProcessor,
) -> FluentPipelineBuilder

Append one buffer-level frame processor and return this builder.

with_frame_exporters

with_frame_exporters(
    exporters: Iterable[IFrameExporter],
) -> FluentPipelineBuilder

Replace file-backed exporters that run after frame processing.

add_frame_exporter

add_frame_exporter(
    exporter: IFrameExporter,
) -> FluentPipelineBuilder

Add a final-output exporter for processed frames.

with_signal_cleaners

with_signal_cleaners(
    cleaners: Iterable[ISignalCleaner],
) -> FluentPipelineBuilder

Replace signal cleaners and return this builder.

add_signal_cleaner

add_signal_cleaner(
    cleaner: ISignalCleaner,
) -> FluentPipelineBuilder

Append one signal cleaner and return this builder.

with_analyzers

with_analyzers(
    analyzers: Iterable[IAnalyzer],
) -> FluentPipelineBuilder

Replace analyzers and return this builder.

add_analyzer

add_analyzer(analyzer: IAnalyzer) -> FluentPipelineBuilder

Append one analyzer and return this builder.

with_visualizers

with_visualizers(
    visualizers: Iterable[IVisualizer],
) -> FluentPipelineBuilder

Replace visualizers applied to all analyzer results.

add_visualizer

add_visualizer(
    visualizer: IVisualizer,
) -> FluentPipelineBuilder

Append one visualizer applied to all analyzer results.

with_visualizer_bindings

with_visualizer_bindings(
    bindings: Iterable[VisualizerBinding],
) -> FluentPipelineBuilder

Replace selective visualizer bindings and return this builder.

add_visualizer_for_results

add_visualizer_for_results(
    visualizer: IVisualizer, result_indices: Iterable[int]
) -> FluentPipelineBuilder

Bind one visualizer to selected analyzer result indexes.

with_intermediate_frame_capture

with_intermediate_frame_capture(
    config: IntermediateFrameCaptureConfig | dict | None,
) -> FluentPipelineBuilder

Enable or disable bounded intermediate frame capture.

with_intermediate_frame_visualizers

with_intermediate_frame_visualizers(
    visualizers: Iterable[IVisualizer],
) -> FluentPipelineBuilder

Replace visualizers dedicated to intermediate frame collections.

add_intermediate_frame_visualizer

add_intermediate_frame_visualizer(
    visualizer: IVisualizer,
) -> FluentPipelineBuilder

Add a visualizer dedicated to intermediate frame collections.

with_stream_runtime

with_stream_runtime(
    config: StreamRuntimeConfig | dict | None,
) -> FluentPipelineBuilder

Configure bounded buffers and latency policy for adaptive streaming.

build_context

build_context() -> PipelineContext

Build and return the PipelineContext from the configured components.

ConfigPipelineBuilder

Build a validated PipelineContext from a declarative configuration.

Design rationale

ConfigPipelineBuilder exists for deployment scenarios where the pipeline topology is owned by YAML, JSON, an API payload, or a UI editor rather than by Python construction code.

The builder delegates all component construction to PluginRegistry. It knows category names and schema structure, but it does not import concrete frame extractors, processors, analyzers, or visualizers. This keeps the core configuration layer independent from infrastructure adapters.

Configuration schema
schema_version: "1.0"
pipeline:
  frame_extractor:
    name: opencv_buffered
    params:
      path: /path/to/video.mp4

  frame_processors:
    - name: opencv_gray
      processor_type: single_frame
    - name: motion_magnification
      processor_type: frame_buffer

  signal_extractor:
    name: opencv_tracker
    params:
      roi: [100, 200, 50, 80]

  signal_cleaners:
    - name: moving_average
      params:
        window: 5

  analyzers:
    - name: vertical_position

  visualizers:
    - name: matplotlib
      result_indices: [0]

  intermediate_frames:
    enabled: true
    sampling_interval: 10
    max_stored_frames: 20
    export_directory: artifacts/debug
    lazy_saving: true
    visualizers:
      - name: intermediate_frames_grid

  runtime:
    frame_buffer_size: 8
    signal_buffer_size: 8
    data_buffer_size: 8
    latency_policy:
      name: blocking
      params: {}
Versioning

Configs are normalized through normalize_pipeline_config. Unversioned configs are accepted as the current public schema for compatibility, while unsupported explicit versions raise ConfigVersionError.

Mutability

The input mapping is read and copied into a new PipelineContext; callers should not rely on later mutations to the original mapping.

Raises:

Type Description
PipelineConfigurationError

If a required section is missing, a plugin entry is malformed, a plugin cannot be found, plugin construction fails, or the resulting context violates PipelineContext invariants.

build_context

build_context(config: Mapping[str, Any]) -> PipelineContext

Resolve a versioned config into an immutable PipelineContext.

Parameters:

Name Type Description Default
config Mapping[str, Any]

Mapping containing a top-level pipeline section and, optionally, a schema_version string.

required

Returns:

Type Description
PipelineContext

Validated context containing constructed component instances, runtime settings, visualizer bindings, intermediate-frame capture configuration, and a compact reproducibility copy of the source config.

Raises:

Type Description
ConfigSchemaError

If required sections are missing or have the wrong shape.

ConfigVersionError

If schema_version is explicit and unsupported.

PluginResolutionError

If the registry cannot resolve a configured component name.

PluginConstructionError

If a plugin factory raises or receives invalid parameters.

PipelineConfigurationError

If context validation fails after plugin construction.

VisualizerBinding dataclass

Binds a visualizer to selected analyzer result indexes.

result_indices=None preserves the default behaviour: the visualizer is applied to every analyzer result. Providing indexes makes the binding selective without changing the visualizer contract.

target_indexes

target_indexes(result_count: int) -> tuple[int, ...]

Resolve this binding against the available analyzer result indexes.

The method belongs to the value object because index validation is part of the binding contract, not a concern of planner or renderer code.

Planning and Runtime Policy

ExecutionPlanStage dataclass

Public description of one stage in an execution plan.

The value is generated before execution starts and is safe to display in UIs, logs, or diagnostics. It contains decisions and rationale, not runtime executor objects.

Attributes:

Name Type Description
stage_id str

Stable stage identifier used in logs and errors.

stage_group str

Logical stage group, such as frame_extraction, analysis, or visualisation.

component_name str

Human-readable component class name.

execution_mode str

Selected mode, usually batch or streaming.

capabilities StageCapabilities

Capabilities declared by the component.

materializes_input bool

Whether the stage creates a materialization boundary.

reason str

Policy explanation for the selected execution mode.

streams property

streams: bool

Return True when this stage is planned for streaming execution.

as_dict

as_dict() -> dict[str, Any]

Return a JSON-safe stage descriptor for APIs, UIs, and logs.

PipelineExecutionPlan dataclass

Public execution plan generated before a pipeline run starts.

The plan is an observability contract. It explains which stages are streamable, where the runtime will materialize data, and why each decision was selected by the execution policy.

streamable_end_to_end property

streamable_end_to_end: bool

Return whether all stages preserve streaming without materialization.

materialization_boundaries property

materialization_boundaries: tuple[ExecutionPlanStage, ...]

Return stages that explicitly materialize an upstream stream.

by_group

by_group(group: str) -> tuple[ExecutionPlanStage, ...]

Return stages belonging to a logical group.

Parameters:

Name Type Description Default
group str

Stage group identifier.

required

as_dict

as_dict() -> dict[str, Any]

Return a JSON-safe execution plan for metadata and API responses.

as_text

as_text() -> str

Return a stable, human-readable execution plan summary.

PipelineExecutionMode

Bases: str, Enum

Execution modes that can be selected for one pipeline stage.

PipelineExecutionDecision dataclass

Policy decision for one stage.

The decision carries both the selected mode and the reason that will appear in execution plans. Keeping the explanation in the policy prevents planner and runtime from inventing separate narratives for the same choice.

streams property

streams: bool

Return True when this decision selects streaming execution.

PipelineStagePolicyContext dataclass

Inputs available to execution-mode policies for one stage.

The context contains facts, not decisions: capabilities, current stream state, downstream demand and optional cost estimates. This keeps policies replaceable and testable without depending on executor internals.

PipelineExecutionPolicy

Bases: Protocol

Strategy interface for batch/streaming execution decisions.

Custom policies can implement latency-first, memory-first, observability or domain-specific rules without changing the execution planner or runtime. Implementations must never select streaming when stage_streamable is false.

decide_source

decide_source(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Choose how a source stage should produce its output.

Implementations must return batch mode when context.stage_streamable is False.

decide_stage

decide_stage(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Choose how a transformation, cleaner, exporter, or processor should run.

The decision should preserve an active stream when possible and should avoid opening a stream when downstream stages cannot consume it.

decide_analyzer

decide_analyzer(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Choose how an analyzer should consume signal input.

Streaming analyzer decisions affect whether progressive visualizers can receive intermediate data during a run.

DefaultPipelineExecutionPolicy

Default cost-aware streaming policy.

The policy keeps streaming when it avoids materializing an active stream, starts new streaming segments only when there is downstream demand, and uses available size estimates to prefer bounded queues over full materialization when that is clearly cheaper.

decide_source

decide_source(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Select source execution mode from source capability and downstream demand.

Returns:

Type Description
PipelineExecutionDecision

Batch when no progressive consumer benefits from a stream; streaming when a downstream stage can consume frames progressively.

decide_stage

decide_stage(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Select execution mode for non-analyzer processing stages.

The default policy keeps an active stream whenever the stage can process it and uses memory estimates to prefer bounded queues over full materialization when both estimates are available.

decide_analyzer

decide_analyzer(
    context: PipelineStagePolicyContext,
) -> PipelineExecutionDecision

Select analyzer execution mode.

Streaming is selected when the analyzer can consume an active stream or when a progressive visualizer creates demand for analyzer updates.

StreamRuntimeConfig dataclass

Bounded-buffer and latency settings for adaptive streaming execution.

The config controls queue capacities between streaming stages and selects the frame latency policy used by streaming frame extractors. It is immutable and safe to store in PipelineContext or reproducibility metadata.

Attributes:

Name Type Description
frame_buffer_size int

Public frame queue capacity between frame source and downstream stages.

signal_buffer_size int

Public signal queue capacity between signal stages and analyzers.

data_buffer_size int

Public data queue capacity between streaming analyzers and visualizers.

latency_policy LatencyPolicyConfig

Serializable latency-policy selector.

from_mapping classmethod

from_mapping(
    value: Mapping[str, Any] | None,
) -> StreamRuntimeConfig

Parse runtime settings from a declarative config mapping.

Parameters:

Name Type Description Default
value Mapping[str, Any] | None

Mapping from pipeline.runtime, or None for defaults.

required

Returns:

Type Description
StreamRuntimeConfig

Validated runtime config.

Raises:

Type Description
ConfigSchemaError

If pipeline.runtime or a buffer size has an invalid shape.

LatencyPolicyError

If the nested latency-policy config is invalid.

validate

validate() -> None

Validate buffer-size invariants.

Raises:

Type Description
ConfigSchemaError

If any public buffer capacity is less than one.

as_dict

as_dict() -> dict[str, Any]

Return a JSON-safe representation for exported configs and plans.

LatencyPolicyConfig dataclass

Serializable selector for frame-stream latency behavior.

The config is stored in pipeline configs and run metadata. Calling create() returns a fresh policy instance because concrete policies keep per-run counters and, for adaptive sampling, per-run control state.

Attributes:

Name Type Description
name str

One of blocking, drop_newest, drop_oldest, or adaptive_sampling.

params Mapping[str, Any]

Policy-specific parameters. Only adaptive sampling currently consumes parameters.

from_mapping classmethod

from_mapping(
    value: Mapping[str, Any] | None,
) -> LatencyPolicyConfig

Parse a latency policy mapping from declarative config.

Parameters:

Name Type Description Default
value Mapping[str, Any] | None

Mapping from pipeline.runtime.latency_policy, or None to select the default blocking policy.

required

Returns:

Type Description
LatencyPolicyConfig

Normalized, lower-case policy selector.

Raises:

Type Description
LatencyPolicyError

If the mapping shape, policy name, or params section is invalid.

create

create() -> FrameLatencyPolicy

Create a fresh stateful policy instance for one pipeline run.

Returns:

Type Description
FrameLatencyPolicy

Runtime strategy used by streaming frame extractors.

Raises:

Type Description
LatencyPolicyError

If name is not supported or policy-specific params are invalid.

as_dict

as_dict() -> dict[str, Any]

Return a JSON-safe representation for configs and run metadata.

FrameLatencyPolicy

Bases: ABC

Strategy used by streaming frame extractors under queue pressure.

Implementations decide whether an incoming frame should be published, dropped, or used to replace an older queued frame. Instances may keep counters, so they are per-run runtime objects rather than reusable config values.

publish abstractmethod

publish(frame: Frame, output_buffer: IFrameBuffer) -> bool

Publish frame to output_buffer or drop it.

Parameters:

Name Type Description Default
frame Frame

Incoming frame from a streaming source.

required
output_buffer IFrameBuffer

Bounded frame queue feeding downstream stages.

required

Returns:

Type Description
bool

True when the frame was accepted by the output buffer.

metrics

metrics() -> dict[str, Any]

Return runtime counters for observability.

BlockingFrameLatencyPolicy

Bases: FrameLatencyPolicy

Preserve every frame by blocking upstream when the queue is full.

Use this policy for offline reproducibility and deterministic frame coverage. It can increase latency in realtime pipelines when downstream inference or visualization is slower than the source.

DropNewestFrameLatencyPolicy

Bases: FrameLatencyPolicy

Drop the incoming frame when the downstream queue is full.

This policy protects downstream stages from backlog growth while preserving already queued frames. It is useful when continuity of accepted frames is more important than visual freshness.

DropOldestFrameLatencyPolicy

Bases: FrameLatencyPolicy

Keep preview latency low by replacing stale queued frames.

This policy favors the most recent source frame and is usually the best default for realtime camera previews where freshness is more important than processing every frame.

AdaptiveSamplingFrameLatencyPolicy

Bases: FrameLatencyPolicy

Reduce processed FPS by increasing the sampling interval under queue pressure.

The policy is intentionally simple and deterministic: it observes the target queue fill ratio before each publish and adjusts the sampling interval within configured bounds. This stabilizes live preview latency without adding worker coordination complexity.

from_mapping classmethod

from_mapping(
    params: Mapping[str, Any],
) -> AdaptiveSamplingFrameLatencyPolicy

Build an adaptive policy from config params.

Parameters:

Name Type Description Default
params Mapping[str, Any]

Mapping with optional min_interval, max_interval, high_watermark, and low_watermark values.

required

Raises:

Type Description
LatencyPolicyError

If numeric params cannot be coerced or violate invariants.

Configuration Versioning

PipelineConfigMigration dataclass

Declarative migration step between two config schema versions.

Migrations are intentionally pure: they receive a mapping and return a new mapping. This keeps future schema evolution testable and prevents builders from mutating user-provided configuration objects.

apply

apply(config: Mapping[str, Any]) -> dict[str, Any]

Apply the migration to a config mapping.

Parameters:

Name Type Description Default
config Mapping[str, Any]

Source config in source_version schema.

required

Returns:

Type Description
dict[str, Any]

Migrated config with schema_version set to target_version.

Raises:

Type Description
ConfigVersionError

If the migration function does not return a mapping.

VersionedPipelineConfig dataclass

Normalized pipeline configuration plus schema-version metadata.

Attributes:

Name Type Description
root Mapping[str, Any]

Canonical top-level config mapping after migration.

pipeline Mapping[str, Any]

Canonical pipeline section consumed by ConfigPipelineBuilder.

schema_version str

Resolved public schema version.

explicit_version bool

Whether the user supplied schema_version.

applied_migrations tuple[str, ...]

Ordered migration labels applied during normalization.

source_config

source_config() -> dict[str, Any]

Return a compact source config safe to store in PipelineContext.

PipelineConfigVersionManager dataclass

Validate and normalize declarative pipeline config versions.

The current implementation supports the first public schema, 1.0. The migration list is an explicit extension point for future schema changes without pushing version conditionals into ConfigPipelineBuilder.

normalize

normalize(
    config: Mapping[str, Any],
) -> VersionedPipelineConfig

Validate, migrate, and canonicalize a pipeline config.

Parameters:

Name Type Description Default
config Mapping[str, Any]

User-provided top-level configuration mapping.

required

Returns:

Type Description
VersionedPipelineConfig

Canonical config plus version metadata.

Raises:

Type Description
ConfigSchemaError

If the root or pipeline section has an invalid shape.

ConfigVersionError

If the explicit schema version is malformed or unsupported.

normalize_pipeline_config

normalize_pipeline_config(
    config: Mapping[str, Any],
) -> VersionedPipelineConfig

Normalize a user config using the default public schema-version policy.

This helper is the public convenience entry point used by ConfigPipelineBuilder.

Run Snapshots

PipelineRunState

Bases: StrEnum

Observable lifecycle states for a pipeline run.

PipelineRunSnapshot dataclass

Immutable snapshot of a pipeline run.

Timestamps use time.time() seconds to stay consistent with the existing event timestamp model.