gabriel / musehub public
feat BREAKING task/spectral-sigil-avatar #1 / 1
AI Agent gabriel · 144 days ago · Apr 30, 2026 · Diff

feat: add Spectral Sigil content-addressed SVG avatar system

- musehub/services/spectral_sigil.py — pure Python SVG generator (~180 lines) * 5-layer system: chromatic field, archetype core, orbital rings, domain dots, handle initial * derive_hue() extracts hue 0-359 from identity_id bytes 0-3 * human=bezier blob, agent=hex circuit, org=quorum polygon (archetype-distinct shapes) * orbital ellipses from bytes 8-15; domain dots colored by live activity * dormant state (no activity) uses grayscale dots at 40% opacity * fully deterministic: same inputs → identical SVG bytes - musehub/api/routes/musehub/ui_avatars.py — GET /avatars/{identity_id}.svg * validates 64-char hex identity_id → 400 for invalid * fetches identity from DB → 404 if not found * returns SVG with Cache-Control: public, max-age=31536000, immutable * registered early in main.py (before /{owner}/{repo_slug} wildcard) - musehub/api/routes/musehub/__init__.py — add ui_avatars to _DIRECT_REGISTERED - musehub/main.py — include avatar_router before wildcard UI routes - profile.html — Spectral Sigil <img> in hero (96×96, positioned absolute top-right) - _user-profile.scss — .prof-sigil-wrap/.prof-sigil styles with glow shadow - tests/test_spectral_sigil.py — 28 TDD tests (all GREEN) * generator unit tests: returns bytes, valid SVG, deterministic, archetype-distinct * derive_hue formula tests * domain dot color tests (dormant vs. active per domain) * HTTP route tests: 200, valid SVG, immutable cache, 404 unknown, 400 invalid id

sha256:2a055247b917e5145dfca9da0962db6b9447f72bd4c213ff983d21fbf994f61a sha
+79 ~12 symbols
sha256:2c68985f1b9f5404035b3a09400ed157ff2dde8bbfea4a1f28627401473ce3a0 snapshot
+79
symbols added
~12
symbols modified
0
dead code introduced
Semantic Changes 91 symbols
+ _CACHE_HEADERS variable variable _CACHE_HEADERS L25–28
+ _HEX64_RE variable variable _HEX64_RE L23–23
+ _fetch_identity function async_function _fetch_identity L31–40
+ get_sigil function async_function get_sigil L44–67
+ APIRouter import import APIRouter L12–12
+ AsyncSession import import AsyncSession L15–15
+ HTTPException import import HTTPException L12–12
+ Response import import Response L13–13
+ _db import import _db L17–17
+ annotations import import annotations L8–8
+ dbm import import dbm L18–18
+ generate_sigil import import generate_sigil L19–19
+ re import import re L10–10
+ select import import select L14–14
+ router variable variable router L21–21
~ musehub/services/spectral_sigil.py .py 15 symbols added
+ DOMAIN_COLORS variable variable DOMAIN_COLORS L24–30
+ _DORMANT_DOT_COLOR variable variable _DORMANT_DOT_COLOR L32–32
+ _DORMANT_DOT_OPACITY variable variable _DORMANT_DOT_OPACITY L33–33
+ _archetype_core function function _archetype_core L125–139
+ _blob_core function function _blob_core L142–175
+ _domain_dots function function _domain_dots L266–305
+ _hex_core function function _hex_core L178–209
+ _orbital_rings function function _orbital_rings L246–263
+ _palette function function _palette L116–122
+ _polygon_core function function _polygon_core L212–243
+ derive_hue function function derive_hue L40–43
+ generate_sigil function function generate_sigil L46–108
+ Final import import Final L18–18
+ annotations import import annotations L15–15
+ math import import math L17–17
~ tests/test_spectral_sigil.py .py 45 symbols added
+ _AGENT_ID variable variable _AGENT_ID L26–26
+ _HUMAN_ID variable variable _HUMAN_ID L25–25
+ _KNOWN_HUE_ID variable variable _KNOWN_HUE_ID L30–30
+ _ORG_ID variable variable _ORG_ID L27–27
+ _make_identity_mock function function _make_identity_mock L37–48
+ _parse_svg function function _parse_svg L33–34
+ ASGITransport import import ASGITransport L16–16
+ AsyncClient import import AsyncClient L16–16
+ AsyncMock import import AsyncMock L13–13
+ ET import import ET L12–12
+ MagicMock import import MagicMock L13–13
+ annotations import import annotations L8–8
+ app import import app L18–18
+ hashlib import import hashlib L10–10
+ patch import import patch L13–13
+ pytest import import pytest L15–15
+ re import import re L11–11
+ test_agent_sigil_contains_polygon_or_path function function test_agent_sigil_contains_polygon_or_path L139–149
+ test_archetypes_produce_distinct_svgs function function test_archetypes_produce_distinct_svgs L165–175
+ test_avatar_route_deterministic_across_requests function async_function test_avatar_route_deterministic_across_requests L389–403
+ test_avatar_route_has_immutable_cache_headers function async_function test_avatar_route_has_immutable_cache_headers L345–359
+ test_avatar_route_returns_200_for_valid_id function async_function test_avatar_route_returns_200_for_valid_id L310–324
+ test_avatar_route_returns_400_for_invalid_id function async_function test_avatar_route_returns_400_for_invalid_id L378–385
+ test_avatar_route_returns_404_for_unknown_id function async_function test_avatar_route_returns_404_for_unknown_id L363–374
+ test_avatar_route_svg_body_is_valid function async_function test_avatar_route_svg_body_is_valid L328–341
+ test_domain_dot_code_color_present_when_active function function test_domain_dot_code_color_present_when_active L238–246
+ test_domain_dot_midi_color_present_when_active function function test_domain_dot_midi_color_present_when_active L257–262
+ test_domain_dot_mpay_color_present_when_active function function test_domain_dot_mpay_color_present_when_active L265–270
+ test_domain_dot_music_color_present_when_active function function test_domain_dot_music_color_present_when_active L249–254
+ test_domain_dots_absent_when_no_activity function function test_domain_dots_absent_when_no_activity L224–235
+ test_generate_sigil_deterministic_same_domains function function test_generate_sigil_deterministic_same_domains L103–109
+ test_generate_sigil_deterministic_same_id function function test_generate_sigil_deterministic_same_id L95–100
+ test_generate_sigil_differs_by_identity_id function function test_generate_sigil_differs_by_identity_id L112–117
+ test_generate_sigil_has_viewbox function function test_generate_sigil_has_viewbox L87–92
+ test_generate_sigil_is_valid_svg function function test_generate_sigil_is_valid_svg L78–84
+ test_generate_sigil_returns_bytes function function test_generate_sigil_returns_bytes L71–75
+ test_hue_derives_from_identity_id_bytes function function test_hue_derives_from_identity_id_bytes L183–190
+ test_hue_function_importable function function test_hue_function_importable L193–196
+ test_human_sigil_contains_path_element function function test_human_sigil_contains_path_element L125–136
+ test_org_sigil_contains_polygon_or_path function function test_org_sigil_contains_polygon_or_path L152–162
+ test_sigil_contains_ellipse_elements function function test_sigil_contains_ellipse_elements L204–216
+ test_sigil_contains_text_with_first_char function function test_sigil_contains_text_with_first_char L278–289
+ test_sigil_text_initial_matches_handle function function test_sigil_text_initial_matches_handle L292–301
+ test_spectral_sigil_generator_callable function function test_spectral_sigil_generator_callable L60–63
+ test_spectral_sigil_module_importable function function test_spectral_sigil_module_importable L56–57
~ musehub/main.py .py 1 symbol added
+ avatar_router import import avatar_router L68–68
~ src/scss/_user-profile.scss .scss 3 symbols added
+ prof-sigil rule .prof-sigil L401–409
+ prof-sigil-wrap rule .prof-sigil-wrap L390–400
+ prof-sigil:hover rule .prof-sigil:hover L406–408
← Older Oldest on task/spectral-sigil-avatar
All commits
Newer → Latest on task/spectral-sigil-avatar

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:2a055247b917e5145dfca9da0962db6b9447f72bd4c213ff983d21fbf994f61a --body "your comment"