hyperhive/branding/agent-configs.svg
iris a444774ab3 forge: auto-set agent-configs org avatar on core start (#424)
Sibling to ensure_core_avatar (#320). Same one-shot marker-guarded
upload pattern, this time aimed at the Forgejo per-org avatar
endpoint (`POST /api/v1/orgs/{org}/avatar`).

## SVG-to-PNG at build time

Mara: *don't check in the png. instead generate png on the fly or
in build.*

`hive-c0re/build.rs` renders `branding/agent-configs.svg` →
`$OUT_DIR/agent-configs.png` via `rsvg-convert` (librsvg) on every
compile; `forge.rs` then `include_bytes!`s the OUT_DIR PNG. The
raster never gets checked into git — SVG stays source of truth,
the PNG is a build artifact.

- `hive-c0re/Cargo.toml`: declares `build = "build.rs"`
- `flake.nix`: adds `librsvg` to `naersk-lib.buildPackage`
  `nativeBuildInputs` (covers both the runtime package and the
  clippy check derivation) and to the dev shell so local
  `cargo build` finds `rsvg-convert` on PATH.
- For dev builds outside Nix, install librsvg (Debian:
  `librsvg2-bin`, macOS: `brew install librsvg`).

## Icon design

Sibling visual to the main hyperhive mark — same dark base + outer
ring + corner-bracket frame so the family reads at a glance. Centre
swaps the hexagonal hive for a stacked-config-files motif: three
offset sheets, folded-corner affordance, curly-brace `{ }` glyph
telegraphing "config file."

Brace font-size dropped 78→56 + letter-spacing -3 (#424 mara:
"braces cross the boundaries of the page") so the glyphs sit
comfortably inside the 120-wide front sheet with clear breathing
room on the left/right edges. The stack is shifted so the front
sheet centres on canvas-(150, 150); brace text anchors there with
`dominant-baseline=central` for true vertical centring.

## Validation

- `cargo check` clean (only pre-existing warnings).
- One-shot marker honoured: re-runs of `ensure_all` skip after the
  first success; `rm /var/lib/hyperhive/forge-agent-configs-avatar-set`
  forces re-upload (useful for icon revisions).
- Behaviour mirrors the existing `ensure_core_avatar` pattern.

Browser smoke test isn't possible from inside iris's container.
Worth eyeballing post-deploy: `http://localhost:3000/agent-configs`
should show the new avatar where the default identicon used to be.
2026-05-26 00:10:52 +02:00

116 lines
6.1 KiB
XML

<svg width="300" height="300" viewBox="0 0 300 300" role="img" xmlns="http://www.w3.org/2000/svg">
<title>HyperHive · agent-configs</title>
<desc>HyperHive agent-configs org icon — stacked config files, amber on dark, same frame as the main hyperhive mark</desc>
<defs>
<clipPath id="clipH"><circle cx="150" cy="150" r="140"/></clipPath>
</defs>
<g clip-path="url(#clipH)">
<!-- same dark base + faint horizontal scanlines as the parent
hyperhive mark, so the agent-configs org reads as a sibling -->
<rect x="0" y="0" width="300" height="300" fill="#0a0600"/>
<g stroke="#ffb300" stroke-width="0.35" opacity="0.07">
<line x1="0" x2="300" y1="10" y2="10"/> <line x1="0" x2="300" y1="20" y2="20"/>
<line x1="0" x2="300" y1="30" y2="30"/> <line x1="0" x2="300" y1="40" y2="40"/>
<line x1="0" x2="300" y1="50" y2="50"/> <line x1="0" x2="300" y1="60" y2="60"/>
<line x1="0" x2="300" y1="70" y2="70"/> <line x1="0" x2="300" y1="80" y2="80"/>
<line x1="0" x2="300" y1="90" y2="90"/> <line x1="0" x2="300" y1="100" y2="100"/>
<line x1="0" x2="300" y1="110" y2="110"/> <line x1="0" x2="300" y1="120" y2="120"/>
<line x1="0" x2="300" y1="130" y2="130"/> <line x1="0" x2="300" y1="140" y2="140"/>
<line x1="0" x2="300" y1="150" y2="150"/> <line x1="0" x2="300" y1="160" y2="160"/>
<line x1="0" x2="300" y1="170" y2="170"/> <line x1="0" x2="300" y1="180" y2="180"/>
<line x1="0" x2="300" y1="190" y2="190"/> <line x1="0" x2="300" y1="200" y2="200"/>
<line x1="0" x2="300" y1="210" y2="210"/> <line x1="0" x2="300" y1="220" y2="220"/>
<line x1="0" x2="300" y1="230" y2="230"/> <line x1="0" x2="300" y1="240" y2="240"/>
<line x1="0" x2="300" y1="250" y2="250"/> <line x1="0" x2="300" y1="260" y2="260"/>
<line x1="0" x2="300" y1="270" y2="270"/> <line x1="0" x2="300" y1="280" y2="280"/>
</g>
<!-- containment rings, same as parent (visual family) -->
<circle cx="150" cy="150" r="118" fill="none" stroke="#ffb300" stroke-width="1" opacity="0.4"/>
<circle cx="150" cy="150" r="104" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.25" stroke-dasharray="4 6"/>
<!-- stack of three offset config sheets. each sheet is a
dark-fill rectangle outlined in amber, with thin "content
lines" inside to read as a file. offset diagonally so the
stack reads top-down: back / mid / front. front sheet is
centred on the canvas (150, 150) so the curly-brace glyph
at canvas-centre lands at the visual middle of the front
sheet; back and mid peek out top-LEFT so the stack reads
as a pile. -->
<!-- BACK sheet (x=70, y=56 — top-left peek) -->
<g opacity="0.55">
<rect x="70" y="56" width="120" height="148" rx="6" ry="6"
fill="#150c00" stroke="#ffb300" stroke-width="1.4"/>
<g stroke="#ffb300" stroke-width="0.7" opacity="0.55">
<line x1="82" y1="78" x2="164" y2="78"/>
<line x1="82" y1="94" x2="144" y2="94"/>
<line x1="82" y1="110" x2="158" y2="110"/>
<line x1="82" y1="126" x2="132" y2="126"/>
<line x1="82" y1="142" x2="164" y2="142"/>
<line x1="82" y1="158" x2="144" y2="158"/>
<line x1="82" y1="174" x2="154" y2="174"/>
</g>
</g>
<!-- MID sheet (x=80, y=66) -->
<g opacity="0.8">
<rect x="80" y="66" width="120" height="148" rx="6" ry="6"
fill="#1a0f00" stroke="#ffb300" stroke-width="1.6"/>
<g stroke="#ffb300" stroke-width="0.8" opacity="0.7">
<line x1="92" y1="88" x2="174" y2="88"/>
<line x1="92" y1="104" x2="154" y2="104"/>
<line x1="92" y1="120" x2="168" y2="120"/>
<line x1="92" y1="136" x2="142" y2="136"/>
<line x1="92" y1="152" x2="174" y2="152"/>
<line x1="92" y1="168" x2="154" y2="168"/>
<line x1="92" y1="184" x2="164" y2="184"/>
</g>
</g>
<!-- FRONT sheet (x=90, y=76, width=120, height=148 — centred
at canvas (150, 150)). Folded top-right corner + curly-
brace glyph. The brace text is anchored at canvas-centre
which now coincides with the front-sheet centre. -->
<g>
<!-- main rectangle with folded top-right corner cut: draw as a
path so the corner triangle reads as a tab -->
<path d="M 90 76
L 192 76
L 210 94
L 210 224
L 90 224
Z"
fill="#1f1200" stroke="#ffb300" stroke-width="1.8"/>
<!-- folded-corner triangle (lighter fill) -->
<path d="M 192 76 L 210 94 L 192 94 Z"
fill="#2a1900" stroke="#ffb300" stroke-width="1.2"/>
<!-- curly braces — the universal "config file" glyph.
dominant-baseline=central centres the glyph block on the
text y-coordinate so it lands at the front-sheet middle.
font-size dropped 78→56 + tighter letter-spacing (#424
mara: "braces cross the boundaries of the page") so the
glyphs sit comfortably inside the 120-wide sheet with
clear breathing room on the left/right edges. -->
<text x="150" y="150" text-anchor="middle" dominant-baseline="central"
font-family="ui-monospace, 'JetBrains Mono', monospace"
font-size="56" font-weight="700" letter-spacing="-3"
fill="#ffb300" opacity="0.95">{ }</text>
</g>
<!-- thin centerline crosshair, same flourish as the parent -->
<rect x="0" y="143" width="300" height="2" fill="#ffb300" opacity="0.07"/>
</g>
<!-- same outer frame + corner brackets as the parent hyperhive
mark so the two orgs read as a visual family -->
<circle cx="150" cy="150" r="140" fill="none" stroke="#ffb300" stroke-width="2.5"/>
<circle cx="150" cy="150" r="145" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.4" stroke-dasharray="8 4"/>
<g stroke="#ffb300" stroke-width="1.5" fill="none" opacity="0.8">
<path d="M44,44 L20,44 L20,70"/>
<path d="M256,44 L280,44 L280,70"/>
<path d="M44,256 L20,256 L20,230"/>
<path d="M256,256 L280,256 L280,230"/>
</g>
</svg>