From 10413b4d6553d0f8886ff5a73ee2682f7d304203 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Fri, 5 Jun 2026 22:18:47 +0000 Subject: [PATCH] =?UTF-8?q?Release=20v0.51.281=20=E2=80=94=20Release=20IW?= =?UTF-8?q?=20(stage-verdigris=20=E2=80=94=20Verdigris=20emerald/bronze=20?= =?UTF-8?q?skin=20#3602)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the Verdigris dark-only appearance skin (emerald/forest-green + bronze-gold), renamed from the contributor's 'Hermes Agent' to a descriptive material name per maintainer naming convention. Registered across all 5 skin sites (config allowlist, boot.js swatch, index.html FOUC map, i18n in 12 locales, scoped CSS palette) + test. Also fixes the zeus i18n test (zeus is no longer the trailing skin token). Co-authored-by: rodboev --- CHANGELOG.md | 5 ++++ api/config.py | 1 + static/boot.js | 1 + static/i18n.js | 24 +++++++++--------- static/index.html | 2 +- static/style.css | 48 ++++++++++++++++++++++++++++++++++++ tests/test_verdigris_skin.py | 41 ++++++++++++++++++++++++++++++ tests/test_zeus_skin.py | 5 ++-- 8 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 tests/test_verdigris_skin.py diff --git a/CHANGELOG.md b/CHANGELOG.md index bc521480..aa11e38c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ## [Unreleased] +## [v0.51.281] — 2026-06-05 — Release IW (stage-verdigris — Verdigris emerald/bronze skin) + +### Added +- **New "Verdigris" appearance skin** — a dark-only emerald/forest-green palette (`#0F1714` background, `#121D18` sidebar) with bronze-gold accents (`#C89A5A`), named for the green-bronze patina on aged copper. Selectable in Settings → Appearance and via `/theme verdigris`. Fully scoped under `:root.dark[data-skin="verdigris"]` (no bleed into the default appearance or other skins), with component-level accents for the new-chat button, scrollbar, tool cards, tree viewer, session badges/tags, diff blocks, MCP status, and image lightbox. (#3602, @rodboev; closes #3357) + ## [v0.51.280] — 2026-06-05 — Release IV (stage-p3i — Windows self-update restart fix) ### Fixed diff --git a/api/config.py b/api/config.py index 4e39ba8f..16f031ec 100644 --- a/api/config.py +++ b/api/config.py @@ -5127,6 +5127,7 @@ _SETTINGS_SKIN_VALUES = { "nous", "geist-contrast", "zeus", + "verdigris", } _SETTINGS_LEGACY_THEME_MAP = { # Legacy full themes now map onto the closest supported theme + accent skin pair. diff --git a/static/boot.js b/static/boot.js index dd20a0b4..9faba114 100644 --- a/static/boot.js +++ b/static/boot.js @@ -1502,6 +1502,7 @@ const _SKINS=[ {name:'Neon', colors:['#B347FF','#C76BFF','#00DDFF']}, {name:'Geist Contrast', value:'geist-contrast', colors:['#000000','#ffffff','#FFF175']}, {name:'Zeus', colors:['#FFD700','#FFBF00','#1A1A00']}, + {name:'Verdigris', value:'verdigris', colors:['#C89A5A','#0F1714','#22342C']}, ]; const _VALID_THEMES=new Set((_THEMES||[]).map(t=>t.value)); const _VALID_SKINS=new Set((_SKINS||[]).map(s=>(s.value||s.name).toLowerCase())); diff --git a/static/i18n.js b/static/i18n.js index ea964db6..ee6b2fa3 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -202,7 +202,7 @@ const LOCALES = { cmd_terminal: 'Open the workspace terminal', cmd_new: 'Start a new chat session', cmd_usage: 'Toggle token usage display on/off', - cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Switch agent personality', cmd_skills: 'List available Hermes skills', cmd_use: 'Force a skill for the next message', @@ -1539,7 +1539,7 @@ const LOCALES = { cmd_terminal: 'Apri il terminale del workspace', cmd_new: 'Avvia una nuova sessione di chat', cmd_usage: 'Attiva/disattiva visualizzazione uso token', - cmd_theme: 'Cambia aspetto (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Cambia aspetto (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: "Cambia personalità dell'agente", cmd_skills: 'Elenca le skill Hermes disponibili', cmd_use: 'Forza una skill per il prossimo messaggio', @@ -2868,7 +2868,7 @@ const LOCALES = { cmd_terminal: 'ワークスペースのターミナルを開く', cmd_new: '新しいチャットセッションを開始', cmd_usage: 'トークン使用量表示の ON/OFF を切り替え', - cmd_theme: '外観を切り替え (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: '外観を切り替え (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'エージェントのパーソナリティを切り替え', cmd_skills: '利用可能な Hermes スキルを一覧表示', cmd_use: '次のメッセージにスキルを強制適用', @@ -4159,7 +4159,7 @@ const LOCALES = { cmd_terminal: 'Открыть терминал рабочей области', cmd_new: 'Начать новую сессию чата', cmd_usage: 'Показать или скрыть использование токенов', - cmd_theme: 'Переключить внешний вид (тема: system/dark/light, скин: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Переключить внешний вид (тема: system/dark/light, скин: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Переключить личность агента', cmd_skills: 'Показать доступные навыки Hermes', cmd_use: 'Принудительно применить навык к следующему сообщению', @@ -5459,7 +5459,7 @@ const LOCALES = { cmd_terminal: 'Abrir terminal del espacio de trabajo', cmd_new: 'Iniciar una nueva sesión de chat', cmd_usage: 'Activar o desactivar el uso de tokens', - cmd_theme: 'Cambiar apariencia (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Cambiar apariencia (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Cambiar la personalidad del agente', cmd_skills: 'Listar las skills de Hermes disponibles', cmd_use: 'Forzar una skill para el próximo mensaje', @@ -6700,7 +6700,7 @@ const LOCALES = { cmd_terminal: 'Workspace-Terminal öffnen', cmd_new: 'Neue Chat-Sitzung starten', cmd_usage: 'Token-Verbrauchsanzeige umschalten', - cmd_theme: 'Darstellung wechseln (Theme: system/dark/light, Skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Darstellung wechseln (Theme: system/dark/light, Skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Agenten-Persönlichkeit wechseln', cmd_skills: 'Verfügbare Hermes-Skills auflisten', cmd_use: 'Einen Skill für die nächste Nachricht erzwingen', @@ -7992,7 +7992,7 @@ const LOCALES = { cmd_terminal: '打开工作区 Terminal', cmd_new: '新建聊天会话', cmd_usage: '切换 token 用量显示', - cmd_theme: '切换外观(主题:system/dark/light,皮肤:default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: '切换外观(主题:system/dark/light,皮肤:default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: '切换 Agent 人设', cmd_skills: '列出可用的 Hermes 技能', cmd_use: '为下一条消息强制使用技能', @@ -9270,7 +9270,7 @@ const LOCALES = { cmd_terminal: '開啟工作區 Terminal', cmd_new: '開始新的聊天對話', cmd_usage: '開啟或關閉 token 用量顯示', - cmd_theme: '切換外觀(主題:system/dark/light,skin:default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: '切換外觀(主題:system/dark/light,skin:default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: '切換 Agent 角色', cmd_skills: '列出可用的 Hermes 技能', cmd_use: '為下一則訊息強制使用技能', @@ -10518,7 +10518,7 @@ const LOCALES = { cmd_workspace: 'Trocar workspace por nome', cmd_new: 'Iniciar nova sessão de chat', cmd_usage: 'Alternar exibição de uso de tokens', - cmd_theme: 'Trocar aparência (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Trocar aparência (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Trocar personalidade do agente', cmd_skills: 'Listar skills disponíveis do Hermes', cmd_use: 'Forçar uma skill para a próxima mensagem', @@ -11732,7 +11732,7 @@ const LOCALES = { cmd_terminal: '워크스페이스 터미널 열기', cmd_new: '새 채팅 세션 시작', cmd_usage: '토큰 사용량 표시 켜기/끄기', - cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Switch agent personality', cmd_skills: 'List available Hermes skills', cmd_use: 'Force a skill for the next message', @@ -13054,7 +13054,7 @@ const LOCALES = { cmd_terminal: 'Ouvrez le terminal de l\'espace de travail', cmd_new: 'Démarrer une nouvelle session de discussion', cmd_usage: 'Activer/désactiver l\'affichage de l\'utilisation du jeton', - cmd_theme: 'Changer d\'apparence (thème : system/dark/light, skin : default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Changer d\'apparence (thème : system/dark/light, skin : default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Personnalité de l\'agent de commutation', cmd_skills: 'Lister les compétences Hermès disponibles', cmd_use: 'Forcer une compétence pour le prochain message', @@ -14329,7 +14329,7 @@ const LOCALES = { cmd_terminal: 'Çalışma alanı terminalini açın', cmd_new: 'Yeni bir sohbet oturumu başlatın', cmd_usage: 'Token kullanımı ekranını aç/kapat', - cmd_theme: 'Görünümü değiştir (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus)', + cmd_theme: 'Görünümü değiştir (tema: system/dark/light, skin: default/ares/mono/graphite/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous/geist-contrast/zeus/verdigris)', cmd_personality: 'Temsilci kişiliğini değiştir', cmd_skills: 'Mevcut Hermes becerilerini listele', cmd_use: 'Sonraki mesaj için bir beceriyi zorla', diff --git a/static/index.html b/static/index.html index 799d0f71..3697ff3a 100644 --- a/static/index.html +++ b/static/index.html @@ -17,7 +17,7 @@ - + diff --git a/static/style.css b/static/style.css index 53012913..86383f38 100644 --- a/static/style.css +++ b/static/style.css @@ -755,6 +755,54 @@ :root.dark[data-skin="zeus"] .kanban-modal-overlay{background:rgba(0,0,0,.72);} :root.dark[data-skin="zeus"] .kanban-board-switcher-menu{background:linear-gradient(180deg,rgba(24,24,24,.99),rgba(15,15,15,.99));border-color:rgba(255,215,0,0.15);} + /* ═══ VERDIGRIS — emerald/bronze dashboard palette (dark-only) ═══ */ + :root.dark[data-skin="verdigris"]{ + --bg:#0F1714;--sidebar:#121D18;--border:#22342C;--border2:rgba(200,154,90,0.10); + --text:#F3ECDD;--muted:#A8B4A5;--accent:#C89A5A;--blue:#C89A5A;--gold:#C89A5A;--code-bg:#111B17; + --surface:#16211C;--topbar-bg:rgba(15,23,20,.98);--main-bg:rgba(22,33,28,.55); + --focus-ring:rgba(200,154,90,.30);--focus-glow:rgba(200,154,90,.10); + --input-bg:rgba(255,255,255,.025);--hover-bg:rgba(255,255,255,.045); + --strong:#FFF8EB;--em:#D8C5AA;--code-text:#D6AE74;--code-inline-bg:rgba(200,154,90,.08);--pre-text:#F3ECDD; + --accent-hover:#D6AE74;--accent-bg:rgba(200,154,90,.08);--accent-bg-strong:rgba(200,154,90,.14);--accent-text:#E4C28D; + --error:#D26A6A;--success:#719A68;--warning:#D1A45C;--info:#C89A5A; + --radius-sm:1px;--radius-md:2px;--radius-card:2px;--radius-lg:4px; + --surface-subtle:rgba(255,255,255,.02);--surface-subtle-hover:rgba(255,255,255,.04); + --border-subtle:rgba(255,255,255,.06);--border-muted:rgba(255,255,255,.10); + } + /* ── Verdigris skin: component-level overrides ── */ + /* New chat button: gold */ + :root.dark[data-skin="verdigris"] .new-chat-btn{background:var(--accent);border-color:var(--accent);color:#0F1714;font-weight:600;} + :root.dark[data-skin="verdigris"] .new-chat-btn:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:#0F1714;} + /* Scrollbar: gold tint */ + :root.dark[data-skin="verdigris"]::-webkit-scrollbar-thumb{background:rgba(200,154,90,.20);border-radius:3px;} + :root.dark[data-skin="verdigris"]::-webkit-scrollbar-thumb:hover{background:rgba(200,154,90,.35);} + :root.dark[data-skin="verdigris"]{scrollbar-width:thin;scrollbar-color:rgba(200,154,90,.20) transparent;} + /* Tool cards */ + :root.dark[data-skin="verdigris"] .tool-card{background:rgba(200,154,90,0.03);border-color:rgba(200,154,90,0.08);} + :root.dark[data-skin="verdigris"] .tool-card:hover{border-color:rgba(200,154,90,0.18);} + :root.dark[data-skin="verdigris"] .tool-card-running{background:var(--accent-bg);border-color:var(--accent-bg-strong);} + :root.dark[data-skin="verdigris"] .tool-arg-key, + :root.dark[data-skin="verdigris"] .tool-card-more{color:var(--accent-text);} + :root.dark[data-skin="verdigris"] .tool-card-running-dot{background:var(--accent);} + /* Tree viewer: gold family */ + :root.dark[data-skin="verdigris"] .tree-key{color:#C89A5A;} + :root.dark[data-skin="verdigris"] .tree-str{color:#E4C28D;} + :root.dark[data-skin="verdigris"] .tree-num{color:#C89A5A;} + :root.dark[data-skin="verdigris"] .tree-bool{color:#C89A5A;} + /* Session badges/tags */ + :root.dark[data-skin="verdigris"] .session-child-count{background:rgba(200,154,90,.14);color:#E4C28D;} + :root.dark[data-skin="verdigris"] .session-child-count:hover{background:rgba(200,154,90,.24);color:#F0D0A0;} + :root.dark[data-skin="verdigris"] .session-tree-badge{background:rgba(200,154,90,.16);color:#E4C28D;} + :root.dark[data-skin="verdigris"] .session-tag{background:rgba(200,154,90,.16);color:#E4C28D;} + /* Diff blocks */ + :root.dark[data-skin="verdigris"] .diff-block .diff-plus{color:#C89A5A;} + /* MCP status */ + :root.dark[data-skin="verdigris"] .mcp-http{color:#E4C28D;} + :root.dark[data-skin="verdigris"] .mcp-status-active{color:#E4C28D;} + /* Image lightbox */ + :root.dark[data-skin="verdigris"] .img-lightbox-close:hover{background:rgba(200,154,90,.35);} + :root.dark[data-skin="verdigris"] .img-lightbox-nav:hover{background:rgba(200,154,90,.40);} + /* #594: app-dialog light mode overrides — base styles use hardcoded dark gradients */ :root:not(.dark) .app-dialog{ background:linear-gradient(180deg,rgba(240,237,232,.99),rgba(228,224,216,.99)); diff --git a/tests/test_verdigris_skin.py b/tests/test_verdigris_skin.py new file mode 100644 index 00000000..81a68673 --- /dev/null +++ b/tests/test_verdigris_skin.py @@ -0,0 +1,41 @@ +"""Verdigris skin registration and emerald/bronze palette affordances.""" + +from pathlib import Path + +REPO = Path(__file__).parent.parent +CSS = (REPO / "static" / "style.css").read_text(encoding="utf-8") +BOOT_JS = (REPO / "static" / "boot.js").read_text(encoding="utf-8") +CONFIG_PY = (REPO / "api" / "config.py").read_text(encoding="utf-8") +INDEX_HTML = (REPO / "static" / "index.html").read_text(encoding="utf-8") +I18N_JS = (REPO / "static" / "i18n.js").read_text(encoding="utf-8") + + +def test_verdigris_skin_is_registered_in_all_files(): + assert "{name:'Verdigris'" in BOOT_JS + assert "'verdigris':1" in INDEX_HTML + assert '"verdigris"' in CONFIG_PY + + +def test_verdigris_dark_palette_is_emerald(): + assert ':root.dark[data-skin="verdigris"]' in CSS + assert "--bg:#0F1714" in CSS + assert "--sidebar:#121D18" in CSS + assert "--border:#22342C" in CSS + + +def test_verdigris_accent_is_bronze(): + assert "--accent:#C89A5A" in CSS + assert "--accent-hover:#D6AE74" in CSS + assert "--focus-ring:rgba(200,154,90,.30)" in CSS + + +def test_verdigris_has_no_light_variant(): + # The skin is dark-only; no light root block should be registered. + assert ':root[data-skin="verdigris"]{' not in CSS + assert ':root[data-skin=\"verdigris\"]{\n' not in CSS + + +def test_verdigris_i18n_lists_skin_in_all_locales(): + # There are 12 locales; each should now include verdigris as the trailing skin. + # 10 locales use ASCII closing paren, 2 Chinese locales use full-width paren. + assert I18N_JS.count("verdigris)") + I18N_JS.count("verdigris)") == 12 diff --git a/tests/test_zeus_skin.py b/tests/test_zeus_skin.py index 7d064457..10080d37 100644 --- a/tests/test_zeus_skin.py +++ b/tests/test_zeus_skin.py @@ -44,6 +44,5 @@ def test_zeus_modals_are_not_navy(): def test_zeus_i18n_lists_skin_in_all_locales(): - # Zeus is the last skin in each locale's cmd_theme string, so it appears - # as `…/zeus)` rather than `/zeus/`. There are 10 locales. - assert I18N_JS.count("zeus)") == 10 + # There are 12 locales; each should include zeus in the skin list. + assert I18N_JS.count("/zeus/") == 12