API: Interfaces Package

The interfaces package defines ports implemented by extractors, processors, cleaners, analyzers, visualizers, buffers, and orchestration adapters.

Stage Capabilities

StageCapabilities dataclass

Stable execution contract declared by every pipeline stage.

The pipeline runtime uses these flags to build an execution plan without relying on implementation details such as ad-hoc attributes. Concrete stages should be conservative: declare streaming only when they can produce output progressively without requiring the full upstream sequence.

batch classmethod

batch(
    *,
    stateful: bool = True,
    preserves_order: bool = True,
    supports_frame_parallelism: bool = False,
    realtime_safe: bool = False,
) -> StageCapabilities

Return capabilities for stages that require a complete input sequence.

streaming classmethod

streaming(
    *,
    stateful: bool = False,
    preserves_order: bool = True,
    supports_frame_parallelism: bool = False,
    realtime_safe: bool = True,
) -> StageCapabilities

Return capabilities for stages that can process input progressively.

as_dict

as_dict() -> dict[str, bool]

Return a JSON-safe representation used by execution plans and UI.

Batch Component Contracts

IFrameExtractor

Bases: ABC

Batch source contract for frame-producing plugins.

A frame extractor is the pipeline entry point. Batch extractors return a closed FrameBuffer; streaming extractors should additionally implement IStreamingFrameExtractor so the planner can avoid materializing source frames.

Extension guidance

Implementations should keep constructor configuration explicit and should encode frame order through Frame.index when available.

__init__

__init__(config: dict[str, Any] | None = None)

Store optional extractor configuration.

Parameters:

Name Type Description Default
config dict[str, Any] | None

Plugin-specific configuration mapping. The core does not interpret this mapping after construction.

None

extract abstractmethod

extract() -> FrameBuffer

Extract raw frames and return them in a closed buffer.

Returns:

Type Description
FrameBuffer

Buffer containing frames in source order.

ISingleFrameProcessor

Bases: ABC

Contract for stateless or local frame transformations.

Single-frame processors are adapted into the frame-buffer pipeline by the core runtime. Use this contract when processing one frame does not require future or past frames.

__init__

__init__(config: dict[str, Any] | None = None)

Store plugin-specific processor configuration.

process abstractmethod

process(frame: Frame) -> Frame

Transform one frame.

Parameters:

Name Type Description Default
frame Frame

Input frame.

required

Returns:

Type Description
Frame

Processed frame. Implementations may preserve metadata or add metadata needed by later stages.

IFrameBufferProcessor

Bases: ABC

Buffer-level frame processing contract.

Implementations receive the whole frame sequence so both stateless per-frame operations and temporal algorithms can participate in the same frame processing pipeline.

Streaming implementations should also implement IStreamingFrameBufferProcessor when they can publish processed frames progressively without requiring the complete sequence first.

__init__

__init__(config: dict[str, Any] | None = None)

Store plugin-specific processor configuration.

process abstractmethod

process(buffer: FrameBuffer) -> FrameBuffer

Return a processed frame buffer.

Parameters:

Name Type Description Default
buffer FrameBuffer

Input frames in pipeline order.

required

Returns:

Type Description
FrameBuffer

Processed frames. Implementations should preserve order unless documented otherwise.

FrameExportContext dataclass

Runtime metadata passed to frame-buffer exporters.

Attributes:

Name Type Description
pipeline_id str | None

Optional run id.

exporter_name str

Human-readable exporter component name.

execution_metadata Mapping[str, Any]

Metadata supplied by the caller and propagated through the run.

FrameExportResult dataclass

Exporter result that preserves frames for downstream stages.

Exporters may create artifacts but must also return a frame buffer so signal extraction can continue after export.

IFrameExporter

Bases: ABC

Export final artifacts from processed frames without being a frame processor.

Exporters may write file-backed artifacts and must return a buffer that can still be consumed by signal extractors.

export abstractmethod

export(
    buffer: FrameBuffer, context: FrameExportContext
) -> FrameExportResult

Persist or build artifacts from the frame stream.

Parameters:

Name Type Description Default
buffer FrameBuffer

Processed frame stream.

required
context FrameExportContext

Runtime metadata for artifact naming and reproducibility.

required

Returns:

Type Description
FrameExportResult

Forwarded frame buffer plus generated artifacts.

ISignalExtractor

Bases: ABC

Batch contract for converting frames into signal samples.

Signal extractors consume processed frames and produce an ISignal that analyzers can consume. Streaming implementations should also implement IStreamingSignalExtractor and declare streaming capabilities.

__init__

__init__(config: dict[str, Any] | None = None)

Store plugin-specific extractor configuration.

extract abstractmethod

extract(buffer: FrameBuffer) -> ISignal

Extract a signal from a frame buffer.

Parameters:

Name Type Description Default
buffer FrameBuffer

Processed frames in pipeline order.

required

Returns:

Type Description
ISignal

Iterable signal samples preserving frame-time semantics when available.

ISignalCleaner

Bases: ABC

Batch contract for transforming signal samples before analysis.

Cleaners should preserve signal semantics unless their documentation states otherwise. Typical implementations smooth, normalize, filter, or repair samples produced by a signal extractor.

__init__

__init__(config: Dict[str, Any] | None = None)

Store plugin-specific cleaner configuration.

clean abstractmethod

clean(signal: ISignal) -> ISignal

Return a cleaned signal.

Parameters:

Name Type Description Default
signal ISignal

Input signal from the previous extraction or cleaning stage.

required

Returns:

Type Description
ISignal

Cleaned signal for the next cleaner or analyzer.

IAnalyzer

Bases: ABC

Batch contract for turning a signal into analytical data.

An analyzer is the boundary between signal processing and visualization. Streaming analyzers should also implement IStreamingAnalyzer to publish progressive IData values while still returning a final result.

__init__

__init__(config: dict[str, Any] | None = None)

Store plugin-specific analyzer configuration.

analyze abstractmethod

analyze(signal: ISignal) -> IData

Analyze a complete signal.

Parameters:

Name Type Description Default
signal ISignal

Signal after all configured cleaners have run.

required

Returns:

Type Description
IData

UI-agnostic analytical result.

IVisualizer

Bases: ABC

Batch contract for converting analytical data into visual artifacts.

Visualizers must return UI-agnostic VisualArtifact values. They should not require Streamlit containers, OpenCV windows, notebook globals, or web framework state unless they are explicitly adapter implementations outside the core package.

__init__

__init__(config: dict[str, Any] | None = None)

Store plugin-specific visualizer configuration.

render abstractmethod

render(
    data: IData, context: VisualizationContext | None = None
) -> tuple[VisualArtifact, ...]

Build visual artifacts from analytical data.

Parameters:

Name Type Description Default
data IData

Analyzer result to render.

required
context VisualizationContext | None

Optional run metadata, result index, and rendering hints.

None

Returns:

Type Description
tuple[VisualArtifact, ...]

Final or debug artifacts for UI and exporter adapters.

Data Contracts

IData

Bases: ABC

Marker base class for chart-ready analytical data.

ISignal

Bases: ABC

Base contract for ordered signal samples.

Signals are analyzer input values. Batch signal extractors return this complete collection, while streaming extractors publish ISignalSample values progressively into a buffer.

signal property

signal: list[ISignalSample]

Backward-compatible alias for samples.

__init__

__init__(
    samples: Sequence[ISignalSample],
    config: dict[str, Any] | None = None,
)

Create a signal from ordered samples.

Parameters:

Name Type Description Default
samples Sequence[ISignalSample]

Signal samples in analysis order.

required
config dict[str, Any] | None

Optional plugin-specific metadata retained for compatibility.

None

__iter__

__iter__() -> Iterator[ISignalSample]

Iterate samples in analysis order.

__len__

__len__() -> int

Return the number of samples in the signal.

ISignalSample

Bases: ABC

Base contract for one time-indexed signal sample.

Attributes:

Name Type Description
frame_index

Source frame index associated with the sample.

timestamp_seconds

Optional source timestamp in seconds.

metadata

Plugin-specific sample metadata.

__init__

__init__(
    frame_index: int,
    timestamp_seconds: float | None = None,
    metadata: dict[str, Any] | None = None,
)

Create a signal sample value.

Streaming Contracts

IBuffer

Bases: Protocol[T]

Minimal producer-side contract shared by pipeline buffers.

closed property

closed: bool

Return True when the buffer no longer accepts new items.

put

put(item: T) -> None

Publish one item into the buffer.

close

close() -> None

Mark the stream as complete and wake consumers.

IAbortableBuffer

Bases: IBuffer[T], Protocol[T]

Buffer that can interrupt a stream immediately.

abort

abort() -> None

Cancel the stream and unblock waiting producers or consumers.

IBufferSubscription

Bases: Iterator[T], Protocol[T]

Consumer-side stream cursor that can cancel its upstream buffer.

abort

abort() -> None

Cancel the source buffer for cooperative downstream shutdown.

ISubscribableBuffer

Bases: IAbortableBuffer[T], Protocol[T]

Multi-consumer buffer with explicit fan-out configuration.

set_consumer_count

set_consumer_count(consumers: int) -> None

Declare how many consumers must observe each future item.

subscribe

subscribe(consumer_id: int) -> IBufferSubscription[T]

Return a consumer cursor for the configured stream.

IFrameBuffer

Bases: IAbortableBuffer[Frame], Iterable[Frame], Protocol

Frame stream contract required by realtime latency policies.

This intentionally lives outside IBuffer because capacity and dropping are frame-queue concerns, not universal buffer responsibilities.

capacity property

capacity: int

Maximum number of frame items retained by the public queue.

try_put

try_put(frame: Frame) -> bool

Publish without blocking. Return False when the frame is rejected.

drop_oldest

drop_oldest() -> Frame | None

Drop and return the oldest queued frame item, when available.

fill_ratio

fill_ratio() -> float

Return public queue occupancy in the [0, 1] range.

IStreamingFrameExtractor

Bases: IFrameExtractor

Frame extractor that can publish frames into a bounded output stream.

Implementations must close output_buffer on normal completion and should cooperate with the supplied latency policy instead of writing directly with unbounded buffering.

extract_into abstractmethod

extract_into(
    output_buffer: IFrameBuffer,
    latency_policy: FrameLatencyPolicy,
) -> None

Read frames and publish accepted frames into output_buffer.

Parameters:

Name Type Description Default
output_buffer IFrameBuffer

Bounded frame queue owned by the runtime.

required
latency_policy FrameLatencyPolicy

Per-run policy deciding whether each frame is accepted or dropped.

required

IStreamingFrameBufferProcessor

Bases: IFrameBufferProcessor

Frame processor that can transform a stream without materializing it.

Implementations should publish outputs progressively and preserve ordering unless their plugin documentation explicitly states otherwise.

process_into abstractmethod

process_into(
    input_buffer: Iterable[Frame],
    output_buffer: IBuffer[Frame],
    *,
    processor_index: int,
    intermediate_store: IntermediateFrameArtifactStore
    | None,
) -> None

Consume input_buffer and publish processed frames.

Implementations must close output_buffer when finished and should abort cooperatively when downstream consumers abort.

IStreamingFrameExporter

Bases: IFrameExporter

Frame exporter that writes artifacts while forwarding the frame stream.

This contract lets exporters produce file-backed artifacts without forcing the frame stream to be fully materialized before signal extraction.

export_into abstractmethod

export_into(
    frames: Iterable[Frame],
    output_buffer: IBuffer[Frame],
    context: FrameExportContext,
) -> tuple[VisualArtifact, ...]

Export frames and forward each original frame to output_buffer.

IStreamingSignalExtractor

Bases: ISignalExtractor

Signal extractor that emits samples progressively from frame input.

extract_into abstractmethod

extract_into(
    frames: IFrameBuffer,
    output_buffer: IBuffer[ISignalSample],
) -> None

Consume frames and publish signal samples to output_buffer.

IStreamingSignalCleaner

Bases: ISignalCleaner

Signal cleaner that can transform samples progressively.

clean_into abstractmethod

clean_into(
    input_signal: Iterable[ISignalSample],
    output_buffer: IBuffer[ISignalSample],
) -> None

Consume signal samples and publish cleaned samples to output_buffer.

IStreamingAnalyzer

Bases: IAnalyzer

Analyzer that can publish progressive data and still return a final result.

Progressive values feed streaming visualizers during execution. The returned final IData remains the authoritative analyzer result included in PipelineOutputs.

analyze_into abstractmethod

analyze_into(
    signal: Iterable[ISignalSample],
    output_buffer: IBuffer[IData],
) -> IData

Consume signal samples, publish progressive data, and return final data.

IStreamingVisualizer

Bases: IVisualizer

Visualizer that can consume progressive analyzer data.

Streaming visualizers should avoid toolkit-specific blocking calls in core execution paths. For live UI updates, publish through adapter-safe contracts such as realtime sinks or return final artifacts after the stream closes.

render_stream abstractmethod

render_stream(
    data: Iterable[IData],
    context: VisualizationContext | None = None,
) -> tuple[VisualArtifact, ...]

Render from a data stream subscription.

Orchestration Ports

IPipelineFactory

Bases: ABC

Factory port that creates executable Pipeline instances.

Applications can replace this port to inject custom execution policy, event buses, metadata propagation, or pipeline subclasses without changing the orchestrator.

create abstractmethod

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

Create a pipeline facade for a validated context.

Returns:

Type Description
Pipeline

Executable pipeline instance ready for a runner.

IPipelineRunner

Bases: ABC

Executes Pipeline instances synchronously or asynchronously.

Implementations own execution concerns such as active-run tracking, retry, lifecycle events, and monitor registration/completion.

run abstractmethod

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

Execute a pipeline synchronously and return completed outputs.

submit abstractmethod

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

Submit a pipeline for asynchronous execution.

cancel abstractmethod

cancel(pipeline_id: str) -> bool

Cancel queued work for a run id when supported.

active_ids abstractmethod

active_ids() -> list[str]

Return a snapshot of active run ids.

snapshot abstractmethod

snapshot(pipeline_id: str) -> PipelineRunSnapshot | None

Return the latest snapshot for a run id, if known.

snapshots abstractmethod

snapshots() -> list[PipelineRunSnapshot]

Return latest snapshots for all tracked runs.

shutdown abstractmethod

shutdown(wait: bool = True) -> None

Release runner resources and optionally wait for active work.

IPipelineMonitor

Bases: ABC

Port for observable pipeline execution state.

Monitors are read by UIs, APIs, and operators. Implementations should keep state transitions deterministic and should not expose mutable internal storage through snapshots.

register abstractmethod

register(pipeline_id: str) -> None

Record a newly queued pipeline run.

mark_running abstractmethod

mark_running(pipeline_id: str, attempt: int) -> None

Mark a run attempt as actively executing.

complete abstractmethod

complete(pipeline_id: str) -> None

Mark a run as successfully completed.

fail abstractmethod

fail(
    pipeline_id: str, error: Exception | str, attempt: int
) -> None

Mark a run as failed with an observable error message.

terminate abstractmethod

terminate(pipeline_id: str) -> None

Mark a run as cancelled or terminated.

active_ids abstractmethod

active_ids() -> list[str]

Return a snapshot of queued or running pipeline ids.

snapshot abstractmethod

snapshot(pipeline_id: str) -> PipelineRunSnapshot | None

Return the latest snapshot for a run id, if known.

snapshots abstractmethod

snapshots() -> list[PipelineRunSnapshot]

Return latest snapshots for all tracked runs.

IPipelineOutputStore

Bases: ABC

Persistence port for completed pipeline outputs.

Stores may be in-memory, filesystem-backed, database-backed, or service backed. Implementations should treat PipelineOutputs as immutable values.

save abstractmethod

save(pipeline_id: str, outputs: PipelineOutputs) -> None

Persist outputs for a completed run id.

get abstractmethod

get(pipeline_id: str) -> PipelineOutputs | None

Return stored outputs for a run id, if available.

delete abstractmethod

delete(pipeline_id: str) -> None

Remove stored outputs for a run id.

IPipelineValidator

Bases: ABC

Validation port for executable pipeline instances.

Validators are application-level checks. They should not mutate the pipeline and should raise typed configuration or validation errors when a run cannot be accepted.

validate abstractmethod

validate(pipeline: 'Pipeline') -> None

Validate a pipeline before execution.

IEventBus

Bases: ABC

Typed async-first pub/sub interface.

Two publication paths
  • dispatch — synchronous, for use within pipeline execution threads where no event loop is running.
  • publish — async, for external callers operating in an asyncio context.

Per-listener error isolation: a failing handler must never prevent other handlers from receiving the same event.

subscribe abstractmethod

subscribe(event_type: str, handler: EventHandler) -> None

Register a handler for one event type.

Use IEventBus.WILDCARD to observe every event.

unsubscribe abstractmethod

unsubscribe(event_type: str, handler: EventHandler) -> None

Remove a previously registered handler when present.

dispatch abstractmethod

dispatch(event: Event) -> None

Publish an event synchronously.

Implementations should isolate handler failures so one subscriber does not prevent remaining subscribers from receiving the event.

publish abstractmethod async

publish(event: Event) -> None

Publish an event from an async caller.

IRetryPolicy

Bases: ABC

Strategy interface that governs retry behavior for runners.

Design rationale

Extracting the retry decision into its own object follows the Open/Closed Principle: new strategies such as backoff, jitter, or circuit breakers are added by creating a new class, never by editing the runner. The runner calls only two methods:

  • should_retry: binary gate deciding whether to keep trying.
  • wait_seconds: optional pause before the next attempt.

Both receive the 1-based attempt number that just failed, so policies can implement attempt-dependent logic such as exponential backoff.

should_retry abstractmethod

should_retry(attempt: int, error: Exception) -> bool

Decide whether execution should be retried.

Parameters:

Name Type Description Default
attempt int

The 1-based number of the attempt that just failed.

required
error Exception

The exception that caused the failure.

required

Returns:

Type Description
bool

True when the runner should make another attempt. False when the runner should stop and re-raise error.

wait_seconds

wait_seconds(attempt: int) -> float

Seconds to pause before the next attempt.

Override in subclasses that implement backoff strategies. The base implementation returns 0.0 (no wait).

Parameters:

Name Type Description Default
attempt int

The 1-based number of the attempt that just failed.

required

IBranchingRule

Bases: ABC

Strategy that decides IF and HOW to create a secondary pipeline in response to a domain event.

Design rationale

The Orchestrator holds a list of IBranchingRules. When a domain event arrives on the EventBus, each rule is evaluated in order:

  1. matches(event) — should this event trigger a secondary pipeline?
  2. build_context(event) — build the PipelineContext for the new pipeline.

This is the Strategy pattern: users define their own branching logic by subclassing IBranchingRule, without touching the Orchestrator.

Example

class TrackingLostBranch(IBranchingRule): ... def matches(self, event: Event) -> bool: ... return event.event_type == "tracking_lost" ... ... def build_context(self, event: Event) -> PipelineContext: ... return PipelineContext( ... frame_extractor=..., ... signal_extractor=..., ... analyzers=[...], ... )

matches abstractmethod

matches(event: Event) -> bool

Return True if event should trigger a secondary pipeline.

Parameters:

Name Type Description Default
event Event

The domain event published on the EventBus.

required

Returns:

Type Description
bool

True -> build_context() will be called next. False -> this rule is skipped for this event.

build_context abstractmethod

build_context(event: Event) -> PipelineContext

Build the PipelineContext for the secondary pipeline.

Called only when matches(event) returned True.

Parameters:

Name Type Description Default
event Event

The same domain event that matched.

required

Returns:

Type Description
PipelineContext

A fully configured, immutable context ready for execution by a secondary Pipeline.