.nornir/assets/thund-ir.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 400" font-family="-apple-system,Segoe UI,Roboto,sans-serif" font-size="14">
<defs>
<marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0,0 L7,3 L0,6 Z" fill="#555"/>
</marker>
</defs>
<text x="24" y="26" font-weight="700" font-size="16">The Þund IR — author over one IR, run on a pluggable backend</text>
<!-- authoring surfaces (green) -->
<text x="24" y="58" fill="#2f8f4e" font-size="12" font-weight="600">author · 3 surfaces</text>
<rect x="24" y="66" width="168" height="46" rx="8" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.5"/>
<text x="108" y="88" text-anchor="middle" font-weight="600">Rust builder</text>
<text x="108" y="104" text-anchor="middle" fill="#555" font-size="11">Pipeline::new()…with_flow()</text>
<rect x="24" y="128" width="168" height="46" rx="8" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.5"/>
<text x="108" y="150" text-anchor="middle" font-weight="600">RON DSL</text>
<text x="108" y="166" text-anchor="middle" fill="#555" font-size="11">authoring::dsl (serde)</text>
<rect x="24" y="190" width="168" height="46" rx="8" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.5"/>
<text x="108" y="212" text-anchor="middle" font-weight="600">facett editor</text>
<text x="108" y="228" text-anchor="middle" fill="#555" font-size="11">reuse PipelineView</text>
<!-- ONE IR (blue) -->
<rect x="256" y="96" width="196" height="140" rx="8" fill="#eef3fb" stroke="#2b5fb3" stroke-width="1.5"/>
<text x="354" y="122" text-anchor="middle" font-weight="700">one IR — Pipeline</text>
<text x="354" y="146" text-anchor="middle" fill="#555" font-size="12">Datasets (nodes) + Flows (edges)</text>
<text x="354" y="166" text-anchor="middle" fill="#555" font-size="12">Arrow-typed schema</text>
<text x="354" y="186" text-anchor="middle" fill="#555" font-size="12">Batch · Streaming · Cdc</text>
<text x="354" y="214" text-anchor="middle" fill="#2b5fb3" font-size="12" font-style="italic">validate · topo_order · to_sdp</text>
<!-- authoring -> IR arrows -->
<path d="M192,89 C224,110 224,150 256,150" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<path d="M192,151 L256,160" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<path d="M192,213 C224,192 224,180 256,172" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<text x="205" y="128" fill="#2f8f4e" font-size="11">lower</text>
<!-- ExecBackend (orange) -->
<rect x="516" y="112" width="164" height="108" rx="8" fill="#fdf2ec" stroke="#c26a2b" stroke-width="1.5"/>
<text x="598" y="138" text-anchor="middle" font-weight="700">ExecBackend</text>
<text x="598" y="160" text-anchor="middle" fill="#555" font-size="12">check · run</text>
<text x="598" y="180" text-anchor="middle" fill="#555" font-size="12">Capabilities gate</text>
<text x="598" y="200" text-anchor="middle" fill="#c26a2b" font-size="11" font-style="italic">reject un-runnable up front</text>
<path d="M452,166 L516,166" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<text x="462" y="158" fill="#2b5fb3" font-size="11">consumes IR</text>
<!-- backends (purple) -->
<rect x="722" y="96" width="156" height="52" rx="8" fill="#f6eefb" stroke="#7a3fb3" stroke-width="1.5"/>
<text x="800" y="118" text-anchor="middle" font-weight="600">NativeBackend</text>
<text x="800" y="136" text-anchor="middle" fill="#555" font-size="11">Arrow/DataFusion · native</text>
<rect x="722" y="184" width="156" height="52" rx="8" fill="#f6eefb" stroke="#7a3fb3" stroke-width="1.5"/>
<text x="800" y="206" text-anchor="middle" font-weight="600">SparkBackend</text>
<text x="800" y="224" text-anchor="middle" fill="#555" font-size="11">→ SDP · Spark Connect</text>
<path d="M680,150 C702,132 704,124 722,122" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<path d="M680,182 C702,200 704,208 722,210" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<!-- RunEvents (orange) -->
<rect x="516" y="300" width="164" height="52" rx="8" fill="#fdf2ec" stroke="#c26a2b" stroke-width="1.5"/>
<text x="598" y="322" text-anchor="middle" font-weight="600">RunEvent / RunPhase</text>
<text x="598" y="340" text-anchor="middle" fill="#555" font-size="11">QUEUED→…→COMPLETED</text>
<!-- backends -> RunEvents -->
<path d="M800,236 C800,290 720,300 680,320" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<text x="700" y="284" fill="#7a3fb3" font-size="11">emit events</text>
<!-- viewer (blue) -->
<rect x="256" y="300" width="196" height="52" rx="8" fill="#eef3fb" stroke="#2b5fb3" stroke-width="1.5"/>
<text x="354" y="322" text-anchor="middle" font-weight="600">knut-pipelines viewer</text>
<text x="354" y="340" text-anchor="middle" fill="#555" font-size="11">facett · one render for both</text>
<!-- RunEvents -> viewer -->
<path d="M516,326 L452,326" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<text x="462" y="318" fill="#c26a2b" font-size="11">fold onto</text>
</svg>