Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Changed

- **PR #2475** — Refresh the default Hermes WebUI brand mark with a modern geometric caduceus. The favicon/PWA raster assets, titlebar icon, and in-app empty-state logo now share the same simplified wing-and-staff shape so browser tabs, install icons, and first-run chat surfaces present one consistent mark.

## [v0.51.90] — 2026-05-18 — Release BN (stage-383 — 10-PR full sweep batch — empty-gateway messaging history fix + previous-messaging-sessions setting + Kanban board switcher layout + UI/UX demo theme controls + Slice 3c queue/goal RFC gate + keyless custom endpoints + custom-provider remote model catalog parity + auto-compression elapsed timer + new-conversation cold-start guard + Kanban drag-drop detail open fix)

### Fixed
Expand Down Expand Up @@ -41,7 +45,6 @@
### Documentation

- **PR #2503** by @franksong2702 (refs #2502) — Add `docs/CONTRACTS.md` as a public contributor-facing routing index that points UI/UX, runtime/state, and onboarding/setup changes to the relevant public docs (DESIGN.md, AGENTS.md, RFCs, troubleshooting) before contributors edit code or open PRs. Also adds `docs/UIUX-GUIDE.md` synthesizing the calm-developer-console UI/UX principles from DESIGN.md / README.md / THEMES.md / `docs/ui-ux/` into one contributor guide, refreshes the README and THEMES.md skin lists to cover all ten built-in skins (`catppuccin` + `nous`), and tightens the AGENTS.md / CONTRIBUTING.md contribution-style notes for state-layer and evidence requirements. Docs-only — no runtime or maintainer-policy changes.

## [v0.51.88] — 2026-05-18 — Release BL (stage-381 — 3-PR security + UX + lineage batch — session-bound CSRF tokens for unsafe browser requests + quoted-reply selected-text composer append + compression-continuation sidebar collapse)

### Security
Expand Down Expand Up @@ -79,7 +82,6 @@

- **PR #2490** by @nesquena-hermes — Add a Docker runtime smoke gate (`.github/workflows/docker-smoke.yml`) triggered on PRs and pushes to `master` that modify `Dockerfile`, `docker_init.bash`, `docker-compose*.yml`, `.dockerignore`, or `.env.docker.example`. Validates every compose file parses (`docker compose config`), then matrix-runs the single, two-container, and three-container variants end-to-end: rebuilds the local `Dockerfile` and re-tags it as `ghcr.io/nesquena/hermes-webui:latest` so the multi-container variants exercise PR-level changes rather than the previously-released registry image, `docker compose up -d --wait`s with a 120s health window, probes `/health`, and greps startup logs for known-bad signatures (`EROFS`, `Traceback`, `PermissionError`, `error_exit`, `!! ERROR`, `!! Exiting script`, `groupmod: cannot`, `usermod: cannot`, `Failed to set`). Closes the source-only-test gap that let v0.51.84's `:ro`-mount × `chown -h ... {} +` startup regression reach review with 5800+ green pytests. Workflow runs with `permissions: contents: read`, uses per-run project names and a pre-flight orphan reaper for safe concurrency, and unconditionally tears down all volumes/networks in an `EXIT` trap. Two new source-level invariants in `tests/test_docker_docs_and_readonly.py` pin the staging path so the underlying `:ro`-incompatible call doesn't regress.


## [v0.51.86] — 2026-05-17 — Release BJ (stage-379 — 4-PR review-bypass batch — memory-provider session lifecycle + cross-provider /model alias + RuntimeAdapter cancel seam + Fork-from-here messaging coord)

### Fixed
Expand Down
Binary file added docs/pr-media/2467/after-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/pr-media/2467/before-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/pr-media/2467/logo-before-after.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/favicon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/favicon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/favicon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 20 additions & 14 deletions static/favicon-512.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/favicon.ico
Binary file not shown.
38 changes: 21 additions & 17 deletions static/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 24 additions & 20 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,17 @@
<span class="app-titlebar-icon" aria-hidden="true">
<svg viewBox="0 0 64 64" width="16" height="16" aria-hidden="true">
<defs>
<linearGradient id="app-titlebar-gold" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#F5C542"/>
<stop offset="100%" style="stop-color:#D4961C"/>
<linearGradient id="app-titlebar-gold" x1="0" y1="8" x2="0" y2="58" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#FFE08A"/>
<stop offset="0.52" stop-color="#F5C542"/>
<stop offset="1" stop-color="#D4961C"/>
</linearGradient>
</defs>
<rect x="30" y="10" width="4" height="46" rx="2" fill="url(#app-titlebar-gold)"/>
<path d="M30 18 C24 14, 14 14, 10 18 C14 16, 22 16, 28 20" fill="#F5C542" opacity="0.9"/>
<path d="M34 18 C40 14, 50 14, 54 18 C50 16, 42 16, 36 20" fill="#F5C542" opacity="0.9"/>
<circle cx="32" cy="10" r="4" fill="#F5C542"/>
<path d="M18 23 L32 14 L46 23 L38 23 L32 19 L26 23 Z" fill="url(#app-titlebar-gold)"/>
<path d="M11 28 L27 18 L31 21 L20 32 Z" fill="url(#app-titlebar-gold)" opacity="0.95"/>
<path d="M53 28 L37 18 L33 21 L44 32 Z" fill="url(#app-titlebar-gold)" opacity="0.95"/>
<rect x="29" y="16" width="6" height="38" rx="3" fill="url(#app-titlebar-gold)"/>
<circle cx="32" cy="13" r="4.2" fill="#FFE8A6"/>
</svg>
</span>
<span class="app-titlebar-title" id="appTitlebarTitle">Hermes</span>
Expand Down Expand Up @@ -363,22 +365,24 @@
<button id="scrollToBottomBtn" class="scroll-to-bottom-btn" style="display:none" onclick="scrollToBottom()" aria-label="Scroll to bottom" data-i18n-aria-label="session_jump_end_label" data-i18n-title="session_jump_end_label"><span aria-hidden="true">↓</span><span class="session-jump-btn__text" data-i18n="session_jump_end">End</span></button>
<div class="messages" id="messages">
<div class="empty-state" id="emptyState">
<div class="empty-logo"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="80" height="80" aria-label="Hermes caduceus">
<div class="empty-logo"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="80" height="80" aria-label="Hermes WebUI modern geometric caduceus logo">
<defs>
<linearGradient id="hermes-gold" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#F5C542;stop-opacity:1"/>
<stop offset="100%" style="stop-color:#D4961C;stop-opacity:1"/>
<linearGradient id="hermes-empty-logo-gold" x1="0" y1="8" x2="0" y2="58" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#FFE08A"/>
<stop offset="0.52" stop-color="#F5C542"/>
<stop offset="1" stop-color="#D4961C"/>
</linearGradient>
</defs>
<rect x="30" y="10" width="4" height="46" rx="2" fill="url(#hermes-gold)"/>
<path d="M30 18 C24 14, 14 14, 10 18 C14 16, 22 16, 28 20" fill="#F5C542" opacity="0.9"/>
<path d="M30 22 C26 19, 18 19, 14 22 C18 20, 24 20, 28 24" fill="#D4961C" opacity="0.8"/>
<path d="M34 18 C40 14, 50 14, 54 18 C50 16, 42 16, 36 20" fill="#F5C542" opacity="0.9"/>
<path d="M34 22 C38 19, 46 19, 50 22 C46 20, 40 20, 36 24" fill="#D4961C" opacity="0.8"/>
<path d="M32 48 C22 44, 20 38, 26 34 C20 36, 18 42, 24 46 C18 40, 22 30, 30 28 C24 32, 22 38, 28 42" fill="none" stroke="#F5C542" stroke-width="2.5" stroke-linecap="round"/>
<path d="M32 48 C42 44, 44 38, 38 34 C44 36, 46 42, 40 46 C46 40, 42 30, 34 28 C40 32, 42 38, 36 42" fill="none" stroke="#D4961C" stroke-width="2.5" stroke-linecap="round"/>
<circle cx="32" cy="10" r="4" fill="#F5C542"/>
<circle cx="32" cy="10" r="2" fill="#FFF8E1" opacity="0.7"/>
<path d="M18 23 L32 14 L46 23 L38 23 L32 19 L26 23 Z" fill="url(#hermes-empty-logo-gold)"/>
<path d="M11 28 L27 18 L31 21 L20 32 Z" fill="url(#hermes-empty-logo-gold)" opacity="0.95"/>
<path d="M53 28 L37 18 L33 21 L44 32 Z" fill="url(#hermes-empty-logo-gold)" opacity="0.95"/>
<path d="M16 34 L28 24 L31 27 L23 40 Z" fill="#FFE8A6" opacity="0.76"/>
<path d="M48 34 L36 24 L33 27 L41 40 Z" fill="#FFE8A6" opacity="0.76"/>
<rect x="29" y="16" width="6" height="38" rx="3" fill="url(#hermes-empty-logo-gold)"/>
<path d="M29 33 C21 35 20 43 29 46" fill="none" stroke="#FFE8A6" stroke-width="3.2" stroke-linecap="round"/>
<path d="M35 33 C43 35 44 43 35 46" fill="none" stroke="#D4961C" stroke-width="3.2" stroke-linecap="round"/>
<circle cx="32" cy="13" r="4.2" fill="#FFE8A6"/>
<circle cx="32" cy="13" r="2" fill="#F5C542"/>
</svg></div>
<h2 data-i18n="empty_title">What can I help with?</h2>
<p data-i18n="empty_subtitle">Ask anything, run commands, explore files, or manage your scheduled tasks.</p>
Expand Down
33 changes: 33 additions & 0 deletions tests/test_issue2467_logo_refresh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]


def test_modern_geometric_logo_used_for_favicon_and_empty_state():
favicon = (ROOT / "static" / "favicon.svg").read_text()
index = (ROOT / "static" / "index.html").read_text()

assert "Hermes WebUI modern geometric caduceus logo" in favicon
assert "Hermes WebUI modern geometric caduceus logo" in index
assert "hermes-empty-logo-gold" in index
assert 'M18 23 L32 14 L46 23' in favicon
assert 'M18 23 L32 14 L46 23' in index
assert 'M30 18 C24 14' not in favicon
assert 'M30 18 C24 14' not in index


def test_generated_raster_logo_assets_are_present_and_valid():
expected = {
"favicon-32.png": (32, 32),
"favicon-192.png": (192, 192),
"favicon-512.png": (512, 512),
"apple-touch-icon.png": (512, 512),
}
for name, (width, height) in expected.items():
data = (ROOT / "static" / name).read_bytes()
assert data.startswith(b"\x89PNG\r\n\x1a\n")
assert int.from_bytes(data[16:20], "big") == width
assert int.from_bytes(data[20:24], "big") == height

ico = (ROOT / "static" / "favicon.ico").read_bytes()
assert ico[:4] == b"\x00\x00\x01\x00"
Loading