""" Pipeline composition config — source of truth for graph topology. Defines what stages run, in what order, with what branching. Belongs to a profile. Persisted as JSONB. The execution strategy (serial, parallel, distributed) is separate — the runner reads this config and flattens it into a sequence for now. """ from dataclasses import dataclass, field from typing import Any, Dict, List, Optional @dataclass class StageRef: """Reference to a stage in the pipeline graph.""" name: str # stage name (matches StageDefinition.name) branch: str = "trunk" # which branch this belongs to execution_target: str = "local" # local | gpu | lambda | gcp @dataclass class Edge: """Connection between stages in the graph.""" source: str # stage name target: str # stage name condition: str = "" # empty = unconditional, otherwise a routing rule key @dataclass class PipelineConfig: """ Pipeline graph topology + routing rules. Holder model — stages/edges define the graph shape, routing_rules is a JSONB blob for decision tree logic. """ name: str profile_name: str stages: List[StageRef] = field(default_factory=list) edges: List[Edge] = field(default_factory=list) routing_rules: Dict[str, Any] = field(default_factory=dict) PIPELINE_CONFIG_VIEWS = [StageRef, Edge, PipelineConfig]