.nornir/assets/scorecard-ingest.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 344" 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="30" y="30" font-weight="700" font-size="16">Scorecard ingest — parse_scorecard → ScorecardSignals → Finding[]</text>
<!-- source -->
<rect x="30" y="70" width="180" height="150" rx="8" fill="#eef3fb" stroke="#2b5fb3" stroke-width="1.5"/>
<text x="120" y="94" text-anchor="middle" font-weight="600">scorecard --format json</text>
<text x="120" y="120" text-anchor="middle" fill="#555" font-size="12">score (0..10 aggregate)</text>
<text x="120" y="140" text-anchor="middle" fill="#555" font-size="12">repo.name</text>
<text x="120" y="160" text-anchor="middle" fill="#555" font-size="12">checks[] {name, score}</text>
<text x="120" y="190" text-anchor="middle" fill="#888" font-size="11">higher = better;</text>
<text x="120" y="206" text-anchor="middle" fill="#888" font-size="11">-1 = inconclusive</text>
<!-- parse -->
<rect x="280" y="70" width="190" height="90" rx="8" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.5"/>
<text x="375" y="98" text-anchor="middle" font-weight="600">parse_scorecard</text>
<text x="375" y="120" text-anchor="middle" fill="#555" font-size="12">pass at score ≥ 5</text>
<text x="375" y="140" text-anchor="middle" fill="#c26a2b" font-size="12">Dangerous-Workflow INVERTED</text>
<!-- signals -->
<rect x="280" y="185" width="190" height="90" rx="8" fill="#f6eefb" stroke="#7a3fb3" stroke-width="1.5"/>
<text x="375" y="210" text-anchor="middle" font-weight="700">ScorecardSignals</text>
<text x="375" y="232" text-anchor="middle" fill="#555" font-size="12">maintained · branch_protection</text>
<text x="375" y="250" text-anchor="middle" fill="#555" font-size="12">signed_releases · dangerous_workflow</text>
<!-- findings -->
<rect x="540" y="70" width="270" height="205" rx="8" fill="#fdf2ec" stroke="#c26a2b" stroke-width="1.5"/>
<text x="675" y="96" text-anchor="middle" font-weight="600">findings() → Vec<Finding></text>
<text x="560" y="128" fill="#555" font-size="12">overall < 5</text>
<text x="800" y="128" text-anchor="end" fill="#b3452b" font-size="12">Medium · SCORECARD-LOW</text>
<text x="560" y="156" fill="#555" font-size="12">!maintained</text>
<text x="800" y="156" text-anchor="end" fill="#b3452b" font-size="12">Medium · UNMAINTAINED</text>
<text x="560" y="184" fill="#555" font-size="12">dangerous_workflow</text>
<text x="800" y="184" text-anchor="end" fill="#a12" font-size="12" font-weight="700">High · DANGEROUS-WORKFLOW</text>
<text x="560" y="212" fill="#555" font-size="12">!branch_protection</text>
<text x="800" y="212" text-anchor="end" fill="#7a6a2b" font-size="12">Low · NO-BRANCH-PROTECTION</text>
<text x="675" y="250" text-anchor="middle" fill="#888" font-size="11">A14 bus-factor / A24 maintainer-anomaly</text>
<text x="675" y="266" text-anchor="middle" fill="#888" font-size="11">advisory features — inform, never hard-Block</text>
<path d="M210,130 C240,120 250,110 280,105" fill="none" stroke="#555" stroke-width="1.4" marker-end="url(#a)"/>
<path d="M375,160 L375,185" fill="none" stroke="#555" stroke-width="1.4" marker-end="url(#a)"/>
<path d="M470,200 C505,190 510,175 540,165" fill="none" stroke="#555" stroke-width="1.4" marker-end="url(#a)"/>
<text x="120" y="300" fill="#888" font-size="12">offline · pure serde_json · same model the warehouse round-trips (append/load_scorecard)</text>
<text x="120" y="322" fill="#2b5fb3" font-size="12">CLI: modgunn scorecard --path <report.json> [--subject <name>] [--warehouse <root>] → print + persist</text>
</svg>