.nornir/assets/deployment_modes.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 680" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0b1c2e"/>
<stop offset="1" stop-color="#06111d"/>
</linearGradient>
<linearGradient id="chip" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#14384f"/>
<stop offset="1" stop-color="#0e2a3e"/>
</linearGradient>
<linearGradient id="rail" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#173d57"/>
<stop offset="1" stop-color="#0c2438"/>
</linearGradient>
<linearGradient id="slot" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#123448"/>
<stop offset="1" stop-color="#0a2032"/>
</linearGradient>
</defs>
<!-- PCB substrate -->
<rect x="0" y="0" width="1180" height="680" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1">
<line x1="0" y1="76" x2="1180" y2="76"/>
<line x1="0" y1="632" x2="1180" y2="632"/>
</g>
<g fill="#16415c">
<circle cx="40" cy="40" r="2"/><circle cx="1140" cy="40" r="2"/>
<circle cx="40" cy="652" r="2"/><circle cx="1140" cy="652" r="2"/>
</g>
<!-- title -->
<text x="40" y="44" fill="#eaf6ff" font-size="22" font-weight="700">Three modes</text>
<text x="222" y="44" fill="#9fc9e0" font-size="15">the verbs are identical — only <tspan fill="#bfe6ff" font-weight="700">where the source lives</tspan> & who pulls the trigger differs</text>
<!-- legend -->
<g font-size="12.5">
<line x1="744" y1="60" x2="784" y2="60" stroke="#6fd3f5" stroke-width="3"/>
<text x="792" y="64" fill="#cfe6f5">source in (push / pull)</text>
<line x1="1006" y1="60" x2="1046" y2="60" stroke="#7fb0cc" stroke-width="2.5" stroke-dasharray="5 4"/>
<text x="1054" y="64" fill="#cfe6f5">trigger</text>
</g>
<!-- ===================== LANE LABELS (left) ===================== -->
<g font-size="13" font-weight="700">
<text x="36" y="168" fill="#bfe6ff">1 · FAT</text>
<text x="36" y="332" fill="#bfe6ff">2 · SERVER-MONITORED</text>
<text x="36" y="500" fill="#bfe6ff">3 · THIN CLIENT</text>
</g>
<g font-size="10" fill="#86b3cc">
<text x="36" y="184">embedded CLI</text>
<text x="36" y="348">nornir user, poll loop</text>
<text x="36" y="516">client → server</text>
</g>
<!-- =============== FAT LANE =============== -->
<rect x="170" y="120" width="170" height="92" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="255" y="150" fill="#eaf6ff" font-size="13.5" font-weight="700" text-anchor="middle">local checkout</text>
<text x="255" y="169" fill="#9fc9e0" font-size="10" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace"><root>/<name>/</text>
<text x="255" y="186" fill="#86b3cc" font-size="9.5" text-anchor="middle">pristine OR dirty</text>
<text x="255" y="200" fill="#7fa8c4" font-size="9" text-anchor="middle">human put it there</text>
<rect x="340" y="160" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M340 164 H410"/></g>
<circle cx="410" cy="164" r="4" fill="#bfecff"/>
<!-- =============== SERVER-MONITORED LANE =============== -->
<rect x="170" y="284" width="170" height="92" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="255" y="312" fill="#eaf6ff" font-size="13.5" font-weight="700" text-anchor="middle">member git URLs</text>
<text x="255" y="331" fill="#9fc9e0" font-size="10" text-anchor="middle">server clones (HTTPS/SSH)</text>
<text x="255" y="348" fill="#86b3cc" font-size="9.5" text-anchor="middle">always clean (committed ref)</text>
<text x="255" y="362" fill="#7fa8c4" font-size="9" text-anchor="middle">pulled in</text>
<rect x="340" y="324" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M340 328 H410"/></g>
<circle cx="410" cy="328" r="4" fill="#bfecff"/>
<!-- =============== THIN LANE =============== -->
<rect x="170" y="452" width="170" height="92" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="255" y="480" fill="#eaf6ff" font-size="13.5" font-weight="700" text-anchor="middle">local working tree</text>
<text x="255" y="499" fill="#9fc9e0" font-size="10" text-anchor="middle">client owns repo + creds</text>
<text x="255" y="516" fill="#86b3cc" font-size="9.5" text-anchor="middle">pushed to the server</text>
<text x="255" y="530" fill="#7fa8c4" font-size="9" text-anchor="middle">may be dirty</text>
<rect x="340" y="492" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M340 496 H410"/></g>
<circle cx="410" cy="496" r="4" fill="#bfecff"/>
<!-- gitx column -->
<g>
<rect x="410" y="132" width="120" height="64" rx="9" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="470" y="158" fill="#bfe6ff" font-size="12" text-anchor="middle" font-weight="700">gitx: local</text>
<text x="470" y="176" fill="#86b3cc" font-size="9" text-anchor="middle">clone / tag / publish</text>
<rect x="410" y="296" width="120" height="64" rx="9" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="470" y="322" fill="#bfe6ff" font-size="12" text-anchor="middle" font-weight="700">gitx: server</text>
<text x="470" y="340" fill="#86b3cc" font-size="9" text-anchor="middle">clones member remote</text>
<rect x="410" y="464" width="120" height="64" rx="9" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="470" y="490" fill="#bfe6ff" font-size="12" text-anchor="middle" font-weight="700">gitx: client</text>
<text x="470" y="508" fill="#86b3cc" font-size="9" text-anchor="middle">it owns repo + creds</text>
</g>
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M530 164 H600"/>
<path d="M530 328 H600"/>
<path d="M530 496 H600 V470"/>
</g>
<!-- ===================== COMPUTE (the same verbs) ===================== -->
<rect x="600" y="120" width="220" height="424" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="710" y="148" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">compute — same verbs</text>
<text x="710" y="166" fill="#9fc9e0" font-size="10" text-anchor="middle">index · knowledge · gates · docs</text>
<g font-family="'DejaVu Sans Mono', monospace" font-size="11">
<rect x="624" y="184" width="172" height="28" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="638" y="203" fill="#bfe6ff">map / index build</text>
<rect x="624" y="220" width="172" height="28" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="638" y="239" fill="#bfe6ff">knowledge scan</text>
<rect x="624" y="256" width="172" height="28" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="638" y="275" fill="#bfe6ff">release gate / publish</text>
<rect x="624" y="292" width="172" height="28" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="638" y="311" fill="#bfe6ff">docs render</text>
</g>
<text x="710" y="346" fill="#86b3cc" font-size="10" text-anchor="middle">fat: in-process · modes 2/3: on the server</text>
<!-- bench note -->
<rect x="624" y="368" width="172" height="44" rx="8" fill="#0f2c40" stroke="#4f8aab" stroke-width="1.4"/>
<text x="710" y="389" fill="#cfe6f5" font-size="11" text-anchor="middle" font-weight="700">bench run</text>
<text x="710" y="404" fill="#86b3cc" font-size="9" text-anchor="middle">ALWAYS client/local hardware</text>
<text x="710" y="440" fill="#7fa8c4" font-size="10" text-anchor="middle">producers write a warehouse →</text>
<text x="710" y="454" fill="#7fa8c4" font-size="10" text-anchor="middle">they run where the source is</text>
<!-- trigger arrows (dashed) into compute -->
<path d="M255 212 V250 H600" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="6 4"/>
<text x="430" y="244" fill="#86b3cc" font-size="9.5" text-anchor="middle">trigger: human CLI</text>
<path d="M255 376 V410 H600" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="6 4"/>
<text x="430" y="404" fill="#86b3cc" font-size="9.5" text-anchor="middle">trigger: poll loop</text>
<path d="M255 544 V522 H600" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="6 4"/>
<text x="430" y="516" fill="#86b3cc" font-size="9.5" text-anchor="middle">trigger: human CLI → server</text>
<!-- compute -> warehouse -->
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M820 332 H900 V560"/></g>
<!-- ===================== WAREHOUSE + VIZ (right) ===================== -->
<rect x="940" y="120" width="200" height="180" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="1040" y="148" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">warehouse</text>
<text x="1040" y="167" fill="#9fc9e0" font-size="10" text-anchor="middle">one per workspace</text>
<text x="1040" y="183" fill="#86b3cc" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">~/.nornir/workspaces/<n>/</text>
<text x="1040" y="200" fill="#86b3cc" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">builds/warehouse</text>
<text x="1040" y="222" fill="#bfe6ff" font-size="10" text-anchor="middle" font-weight="700">fat: CLI owns redb lock</text>
<text x="1040" y="238" fill="#bfe6ff" font-size="10" text-anchor="middle" font-weight="700">2/3: server is sole writer</text>
<text x="1040" y="262" fill="#7fa8c4" font-size="9.5" text-anchor="middle">same code, same on-disk shape</text>
<text x="1040" y="280" fill="#7fa8c4" font-size="9.5" text-anchor="middle">/home/nornir/… for the server</text>
<rect x="934" y="200" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M1040 560 V300"/></g>
<circle cx="1040" cy="300" r="4" fill="#bfecff"/>
<!-- ===================== GROUND RAIL ===================== -->
<rect x="170" y="552" width="970" height="56" rx="10" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<g fill="#0a1c2c" stroke="#7fc8ea" stroke-width="1.5">
<circle cx="214" cy="580" r="4"/><circle cx="560" cy="580" r="4"/>
<circle cx="900" cy="580" r="4"/><circle cx="1100" cy="580" r="4"/>
</g>
<text x="240" y="579" fill="#dff1ff" font-size="14" font-weight="700">the rule</text>
<text x="330" y="575" fill="#bcd9ec" font-size="11">producers run where the source is · bench stays client-side forever</text>
<text x="330" y="596" fill="#7fa8c4" font-size="10" font-family="'DejaVu Sans Mono', monospace">thin = source pushed in · monitored = source pulled in · same publish path, two ingestion edges</text>
</svg>