website-htmx-rustelo-code/site/public/images/projects/stratumiops_operation-flow-dark.svg
2026-07-10 03:44:13 +01:00

253 lines
20 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1080 780" font-family="ui-monospace, 'JetBrains Mono', monospace">
<defs>
<marker id="af" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#94a3b8"/>
</marker>
<marker id="ag" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#34d399"/>
</marker>
<marker id="ar" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f87171"/>
</marker>
<marker id="aa" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#fbbf24"/>
</marker>
<marker id="av" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#a78bfa"/>
</marker>
<marker id="ab" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#3b82f6"/>
</marker>
</defs>
<!-- background -->
<rect width="1080" height="780" fill="#0f172a"/>
<!-- title -->
<text x="540" y="28" text-anchor="middle" font-size="16" font-weight="700" fill="#f1f5f9">stratumiops — Operation Flow</text>
<text x="540" y="46" text-anchor="middle" font-size="10" fill="#475569">two main flows: knowledge registration · config sealed state — actor-aware, advisory locking</text>
<!-- ═══ SECTION DIVIDER ══════════════════════════════════════════════ -->
<!-- Left flow label -->
<rect x="12" y="56" width="518" height="18" rx="4" fill="#172033" stroke="#34d399" stroke-width="1"/>
<text x="271" y="68" text-anchor="middle" font-size="9" font-weight="600" fill="#34d399" letter-spacing="1">FLOW A — KNOWLEDGE REGISTRATION (stratum register)</text>
<!-- Right flow label -->
<rect x="542" y="56" width="526" height="18" rx="4" fill="#172033" stroke="#3b82f6" stroke-width="1"/>
<text x="805" y="68" text-anchor="middle" font-size="9" font-weight="600" fill="#60a5fa" letter-spacing="1">FLOW B — CONFIG SEALED STATE (stratum config apply)</text>
<!-- ═══════════════════════════════════════════════════════════════════
FLOW A: REGISTER
Steps: actor → lock changelog → form → outputs → release
═══════════════════════════════════════════════════════════════════ -->
<!-- A1: Actor / trigger -->
<rect x="16" y="82" width="148" height="64" rx="6" fill="#1e293b" stroke="#94a3b8" stroke-width="1"/>
<text x="90" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#cbd5e1" letter-spacing="1">ACTOR</text>
<text x="90" y="112" text-anchor="middle" font-size="8" fill="#94a3b8">developer (TTY)</text>
<text x="90" y="124" text-anchor="middle" font-size="8" fill="#94a3b8">agent (piped)</text>
<text x="90" y="136" text-anchor="middle" font-size="8" fill="#94a3b8">ci / admin</text>
<line x1="164" y1="114" x2="182" y2="114" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#af)"/>
<!-- A2: Lock acquire -->
<rect x="184" y="82" width="152" height="64" rx="6" fill="#3b0000" stroke="#f87171" stroke-width="1"/>
<text x="260" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#fca5a5" letter-spacing="1">LOCK ACQUIRE</text>
<text x="260" y="112" text-anchor="middle" font-size="8" fill="#fda4af">mkdir .stratum/locks/changelog</text>
<text x="260" y="124" text-anchor="middle" font-size="8" fill="#fda4af">write PID to lock dir</text>
<text x="260" y="136" text-anchor="middle" font-size="8" fill="#64748b">stale? kill -0 PID → remove</text>
<line x1="336" y1="114" x2="354" y2="114" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#af)"/>
<!-- A3: Form (actor-branching) -->
<rect x="356" y="82" width="170" height="64" rx="6" fill="#2a1a00" stroke="#fbbf24" stroke-width="1"/>
<text x="441" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#fde68a" letter-spacing="1">FORM (actor-aware)</text>
<text x="441" y="112" text-anchor="middle" font-size="8" fill="#fcd34d">developer → typedialog UI</text>
<text x="441" y="124" text-anchor="middle" font-size="8" fill="#fcd34d">agent/ci → nickel-export + tera</text>
<text x="441" y="136" text-anchor="middle" font-size="8" fill="#64748b">forms/*.ncl drives field layout</text>
<line x1="526" y1="114" x2="526" y2="160" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<text x="530" y="140" font-size="7" fill="#fbbf24">filled</text>
<!-- A4: Outputs fan-out -->
<rect x="356" y="162" width="170" height="100" rx="6" fill="#0a2e1a" stroke="#34d399" stroke-width="1"/>
<text x="441" y="178" text-anchor="middle" font-size="9" font-weight="600" fill="#4ade80" letter-spacing="1">REGISTER OUTPUTS</text>
<text x="441" y="193" text-anchor="middle" font-size="8" fill="#86efac">CHANGELOG append (locked)</text>
<text x="441" y="206" text-anchor="middle" font-size="8" fill="#86efac">ADR hint → adrs/adr-NNN.ncl</text>
<text x="441" y="219" text-anchor="middle" font-size="8" fill="#86efac">ontology patch → .ontology/</text>
<text x="441" y="232" text-anchor="middle" font-size="8" fill="#86efac">mode stub → reflection/modes/</text>
<text x="441" y="248" text-anchor="middle" font-size="8" fill="#64748b">optional: trigger config apply</text>
<!-- A5: Lock release -->
<rect x="184" y="178" width="152" height="52" rx="6" fill="#3b0000" stroke="#f87171" stroke-width="1"/>
<text x="260" y="196" text-anchor="middle" font-size="9" font-weight="600" fill="#fca5a5" letter-spacing="1">LOCK RELEASE</text>
<text x="260" y="210" text-anchor="middle" font-size="8" fill="#fda4af">rm -rf .stratum/locks/changelog</text>
<text x="260" y="222" text-anchor="middle" font-size="8" fill="#64748b">triggered by EXIT trap</text>
<!-- outputs → lock release arrow -->
<line x1="356" y1="212" x2="336" y2="212" stroke="#f87171" stroke-width="1.5" marker-end="url(#ar)"/>
<!-- ─── separator A4 → gate validation ─── -->
<line x1="441" y1="262" x2="441" y2="310" stroke="#34d399" stroke-width="1" marker-end="url(#ag)"/>
<!-- A6: Gate/ADR validation -->
<rect x="16" y="312" width="510" height="68" rx="6" fill="#1e293b" stroke="#fbbf24" stroke-width="1"/>
<text x="271" y="330" text-anchor="middle" font-size="9" font-weight="600" fill="#fde68a" letter-spacing="1">ADR CONSTRAINT VALIDATION (stratum adr validate)</text>
<text x="271" y="346" text-anchor="middle" font-size="8" fill="#fcd34d">nickel export adrs/*.ncl | where status == Accepted | get constraints | where severity == Hard</text>
<text x="271" y="360" text-anchor="middle" font-size="8" fill="#fcd34d">for each: nu -c check_hint → exit 0 + no stdout = pass</text>
<text x="271" y="372" text-anchor="middle" font-size="8" fill="#64748b">^nickel export (not plugin cache) — always fresh · Superseded ADRs excluded</text>
<!-- ═══════════════════════════════════════════════════════════════════
FLOW B: CONFIG APPLY
═══════════════════════════════════════════════════════════════════ -->
<!-- vertical separator line -->
<line x1="538" y1="56" x2="538" y2="390" stroke="#334155" stroke-width="1" stroke-dasharray="4,3"/>
<!-- B1: Actor / trigger -->
<rect x="546" y="82" width="148" height="64" rx="6" fill="#1e293b" stroke="#94a3b8" stroke-width="1"/>
<text x="620" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#cbd5e1" letter-spacing="1">ACTOR</text>
<text x="620" y="112" text-anchor="middle" font-size="8" fill="#94a3b8">developer (TTY)</text>
<text x="620" y="124" text-anchor="middle" font-size="8" fill="#94a3b8">agent (piped)</text>
<text x="620" y="136" text-anchor="middle" font-size="8" fill="#94a3b8">ci / admin</text>
<line x1="694" y1="114" x2="712" y2="114" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#af)"/>
<!-- B2: Lock acquire (manifest) -->
<rect x="714" y="82" width="152" height="64" rx="6" fill="#3b0000" stroke="#f87171" stroke-width="1"/>
<text x="790" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#fca5a5" letter-spacing="1">LOCK ACQUIRE</text>
<text x="790" y="112" text-anchor="middle" font-size="8" fill="#fda4af">mkdir .stratum/locks/manifest</text>
<text x="790" y="124" text-anchor="middle" font-size="8" fill="#fda4af">write PID to lock dir</text>
<text x="790" y="136" text-anchor="middle" font-size="8" fill="#64748b">stale? kill -0 PID → remove</text>
<line x1="866" y1="114" x2="884" y2="114" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#af)"/>
<!-- B3: nickel export + hash -->
<rect x="886" y="82" width="178" height="64" rx="6" fill="#172554" stroke="#3b82f6" stroke-width="1"/>
<text x="975" y="98" text-anchor="middle" font-size="9" font-weight="600" fill="#93c5fd" letter-spacing="1">EXPORT + HASH</text>
<text x="975" y="112" text-anchor="middle" font-size="8" fill="#7dd3fc">nickel export &lt;profile&gt;.ncl</text>
<text x="975" y="124" text-anchor="middle" font-size="8" fill="#7dd3fc">sha256(export) → seal.hash</text>
<text x="975" y="136" text-anchor="middle" font-size="8" fill="#64748b">sha256(snapshot) → snapshot_hash</text>
<line x1="975" y1="146" x2="975" y2="162" stroke="#3b82f6" stroke-width="1.5" marker-end="url(#ab)"/>
<!-- B4: write history entry -->
<rect x="886" y="164" width="178" height="80" rx="6" fill="#172554" stroke="#3b82f6" stroke-width="1"/>
<text x="975" y="180" text-anchor="middle" font-size="9" font-weight="600" fill="#93c5fd" letter-spacing="1">HISTORY ENTRY</text>
<text x="975" y="195" text-anchor="middle" font-size="8" fill="#7dd3fc">cfg-&lt;YYYYMMDDTHHmmSS&gt;-&lt;actor&gt;.ncl</text>
<text x="975" y="208" text-anchor="middle" font-size="8" fill="#7dd3fc">ConfigState record (immutable)</text>
<text x="975" y="221" text-anchor="middle" font-size="8" fill="#7dd3fc">seal.hash + snapshot_hash</text>
<text x="975" y="234" text-anchor="middle" font-size="8" fill="#7dd3fc">supersedes: prev entry | null</text>
<line x1="975" y1="244" x2="975" y2="260" stroke="#3b82f6" stroke-width="1.5" marker-end="url(#ab)"/>
<!-- B5: patch manifest -->
<rect x="886" y="262" width="178" height="60" rx="6" fill="#172554" stroke="#3b82f6" stroke-width="1"/>
<text x="975" y="278" text-anchor="middle" font-size="9" font-weight="600" fill="#93c5fd" letter-spacing="1">PATCH MANIFEST</text>
<text x="975" y="293" text-anchor="middle" font-size="8" fill="#7dd3fc">manifest.ncl → active[&lt;profile&gt;]</text>
<text x="975" y="306" text-anchor="middle" font-size="8" fill="#7dd3fc">= &lt;new cfg entry ref&gt;</text>
<text x="975" y="318" text-anchor="middle" font-size="8" fill="#64748b">under manifest lock</text>
<!-- B6: Lock release -->
<rect x="714" y="178" width="152" height="52" rx="6" fill="#3b0000" stroke="#f87171" stroke-width="1"/>
<text x="790" y="196" text-anchor="middle" font-size="9" font-weight="600" fill="#fca5a5" letter-spacing="1">LOCK RELEASE</text>
<text x="790" y="210" text-anchor="middle" font-size="8" fill="#fda4af">rm -rf .stratum/locks/manifest</text>
<text x="790" y="222" text-anchor="middle" font-size="8" fill="#64748b">triggered by EXIT trap</text>
<!-- patch manifest → lock release -->
<line x1="886" y1="292" x2="866" y2="292" stroke="#f87171" stroke-width="1.5" marker-end="url(#ar)"/>
<!-- B7: audit (drift check) sits below -->
<line x1="975" y1="322" x2="975" y2="370" stroke="#3b82f6" stroke-width="1" marker-end="url(#ab)"/>
<!-- ─── B vertical: audit box ─── -->
<rect x="546" y="312" width="510" height="68" rx="6" fill="#1e293b" stroke="#3b82f6" stroke-width="1"/>
<text x="801" y="330" text-anchor="middle" font-size="9" font-weight="600" fill="#93c5fd" letter-spacing="1">DRIFT AUDIT (stratum config audit)</text>
<text x="801" y="346" text-anchor="middle" font-size="8" fill="#7dd3fc">for each profile in manifest: sha256(live profile.ncl) == manifest.active[p].seal.hash</text>
<text x="801" y="360" text-anchor="middle" font-size="8" fill="#7dd3fc">match → clean · mismatch → drift (warn actor, optionally block)</text>
<text x="801" y="372" text-anchor="middle" font-size="8" fill="#64748b">read-only; no lock acquired · rollback: verify snapshot_hash → restore → new apply (forward operation)</text>
<!-- ═══ SUMMARY / EXAMPLES ════════════════════════════════════════════ -->
<rect x="12" y="398" width="1056" height="90" rx="8" fill="#161b26" stroke="#334155" stroke-width="1"/>
<text x="540" y="418" text-anchor="middle" font-size="10" font-weight="700" fill="#94a3b8">actor flows through both paths automatically — locking is per-resource, not global</text>
<rect x="28" y="428" width="230" height="50" rx="5" fill="#0a2e1a" stroke="#166534" stroke-width="1"/>
<text x="143" y="444" text-anchor="middle" font-size="8" fill="#4ade80">stratum.sh register</text>
<text x="143" y="457" text-anchor="middle" font-size="8" fill="#86efac">STRATUM_ACTOR=developer (TTY)</text>
<text x="143" y="470" text-anchor="middle" font-size="8" fill="#64748b">typedialog form → CHANGELOG locked</text>
<rect x="272" y="428" width="230" height="50" rx="5" fill="#2a1a00" stroke="#92400e" stroke-width="1"/>
<text x="387" y="444" text-anchor="middle" font-size="8" fill="#fcd34d">stratum.sh config apply prod</text>
<text x="387" y="457" text-anchor="middle" font-size="8" fill="#fde68a">STRATUM_ACTOR=ci</text>
<text x="387" y="470" text-anchor="middle" font-size="8" fill="#64748b">manifest lock → cfg-ts-ci.ncl written</text>
<rect x="516" y="428" width="230" height="50" rx="5" fill="#1e1b4b" stroke="#4338ca" stroke-width="1"/>
<text x="631" y="444" text-anchor="middle" font-size="8" fill="#a78bfa">stratum.sh config audit</text>
<text x="631" y="457" text-anchor="middle" font-size="8" fill="#818cf8">any actor, no lock needed</text>
<text x="631" y="470" text-anchor="middle" font-size="8" fill="#64748b">sha256 compare live vs seal.hash</text>
<rect x="760" y="428" width="296" height="50" rx="5" fill="#172554" stroke="#1d4ed8" stroke-width="1"/>
<text x="908" y="444" text-anchor="middle" font-size="8" fill="#93c5fd">stratum.sh config rollback &lt;ts&gt;</text>
<text x="908" y="457" text-anchor="middle" font-size="8" fill="#7dd3fc">verify snapshot_hash → restore → new apply</text>
<text x="908" y="470" text-anchor="middle" font-size="8" fill="#64748b">rollback is always a forward operation</text>
<!-- ═══ LEGEND ═══════════════════════════════════════════════════════ -->
<rect x="12" y="502" width="1056" height="58" rx="8" fill="#1e293b" stroke="#334155" stroke-width="1"/>
<text x="40" y="522" font-size="9" fill="#94a3b8">Legend:</text>
<line x1="100" y1="518" x2="132" y2="518" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#af)"/>
<text x="138" y="522" font-size="8" fill="#64748b">main flow</text>
<line x1="220" y1="518" x2="252" y2="518" stroke="#34d399" stroke-width="1.5" marker-end="url(#ag)"/>
<text x="258" y="522" font-size="8" fill="#64748b">pass / ok</text>
<line x1="340" y1="518" x2="372" y2="518" stroke="#f87171" stroke-width="1.5" marker-end="url(#ar)"/>
<text x="378" y="522" font-size="8" fill="#64748b">error / lock release</text>
<line x1="478" y1="518" x2="510" y2="518" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<text x="516" y="522" font-size="8" fill="#64748b">form complete</text>
<line x1="604" y1="518" x2="636" y2="518" stroke="#3b82f6" stroke-width="1.5" marker-end="url(#ab)"/>
<text x="642" y="522" font-size="8" fill="#64748b">config flow (hash/write)</text>
<line x1="748" y1="518" x2="780" y2="518" stroke="#a78bfa" stroke-width="1.5" marker-end="url(#av)"/>
<text x="786" y="522" font-size="8" fill="#64748b">output / audit</text>
<text x="40" y="542" font-size="8" fill="#475569">Lock resources:</text>
<text x="130" y="542" font-size="8" fill="#64748b">changelog (register) · manifest (config apply/rollback) · backlog (backlog done/cancel)</text>
<text x="40" y="555" font-size="8" fill="#475569">History IDs:</text>
<text x="108" y="555" font-size="8" fill="#64748b">cfg-&lt;YYYYMMDDTHHmmSS&gt;-&lt;actor&gt;.ncl — timestamp collision-free, no lock needed for history writes</text>
<!-- ═══ BACKLOG SUB-FLOW ═══════════════════════════════════════════ -->
<rect x="12" y="574" width="1056" height="90" rx="8" fill="#1e293b" stroke="#fbbf24" stroke-width="1"/>
<text x="36" y="592" font-size="9" font-weight="600" fill="#fbbf24" letter-spacing="1">FLOW C — BACKLOG (stratum backlog …)</text>
<rect x="28" y="600" width="170" height="54" rx="5" fill="#1c1917" stroke="#fbbf24" stroke-width="1"/>
<text x="113" y="616" text-anchor="middle" font-size="8" font-weight="600" fill="#fde68a">backlog list|show</text>
<text x="113" y="629" text-anchor="middle" font-size="8" fill="#fcd34d">read backlog.ncl (no lock)</text>
<text x="113" y="642" text-anchor="middle" font-size="8" fill="#64748b">nickel export → filter/sort</text>
<line x1="198" y1="627" x2="216" y2="627" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<rect x="218" y="600" width="178" height="54" rx="5" fill="#1c1917" stroke="#fbbf24" stroke-width="1"/>
<text x="307" y="616" text-anchor="middle" font-size="8" font-weight="600" fill="#fde68a">backlog add</text>
<text x="307" y="629" text-anchor="middle" font-size="8" fill="#fcd34d">no lock (append, unique ID)</text>
<text x="307" y="642" text-anchor="middle" font-size="8" fill="#64748b">typed item: Todo|Bug|Wish|Debt</text>
<line x1="396" y1="627" x2="414" y2="627" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<rect x="416" y="600" width="192" height="54" rx="5" fill="#1c1917" stroke="#f87171" stroke-width="1"/>
<text x="512" y="616" text-anchor="middle" font-size="8" font-weight="600" fill="#fca5a5">backlog done|cancel</text>
<text x="512" y="629" text-anchor="middle" font-size="8" fill="#fda4af">mkdir lock on backlog resource</text>
<text x="512" y="642" text-anchor="middle" font-size="8" fill="#64748b">mutates status field in backlog.ncl</text>
<line x1="608" y1="627" x2="626" y2="627" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<rect x="628" y="600" width="190" height="54" rx="5" fill="#1c1917" stroke="#fbbf24" stroke-width="1"/>
<text x="723" y="616" text-anchor="middle" font-size="8" font-weight="600" fill="#fde68a">backlog promote</text>
<text x="723" y="629" text-anchor="middle" font-size="8" fill="#fcd34d">graduates_to: Adr|Mode|StateTransition</text>
<text x="723" y="642" text-anchor="middle" font-size="8" fill="#64748b">triggers adr or mode stub creation</text>
<line x1="818" y1="627" x2="836" y2="627" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#aa)"/>
<rect x="838" y="600" width="216" height="54" rx="5" fill="#1c1917" stroke="#fbbf24" stroke-width="1"/>
<text x="946" y="616" text-anchor="middle" font-size="8" font-weight="600" fill="#fde68a">backlog roadmap</text>
<text x="946" y="629" text-anchor="middle" font-size="8" fill="#fcd34d">state.ncl dimensions not-yet-reached</text>
<text x="946" y="642" text-anchor="middle" font-size="8" fill="#64748b">open items by priority (read-only)</text>
<text x="1068" y="770" text-anchor="end" font-size="8" fill="#334155">2026-03</text>
</svg>