fix(desktop): restore persisted backend skin after gateway registers it - #76648
fix(desktop): restore persisted backend skin after gateway registers it#76648sarthak-707 wants to merge 1 commit into
Conversation
Backend skins (YAML skins under $HERMES_HOME/skins, e.g. the catppuccin skin referenced from config.yaml) are announced by the gateway on gateway.ready, which fires after the ThemeProvider has already resolved the persisted theme choice. normalizeSkin can't resolve the name yet, so it silently falls back to the default and nothing re-reads the persisted choice once the skin registers. The user's pick is stored, but the app paints the default on every restart. Re-read the persisted skin whenever the backend theme registry grows and adopt it if it now resolves to something we're not already showing. The functional setState preserves reference identity on the no-op path, so unrelated registry churn never re-renders the themed tree.
Related: #71447 repairs persisted backend-skin restart behavior by retaining known skin names before gateway registration, while this PR re-adopts the persisted choice when the backend registry registers it. #75374 covers the separate contributed-theme registry. These are competing semantics, not duplicate patches. |
|
Thanks for the focused regression fix. The premise holds on current The effect in This is an automated hermes-sweeper review. |
SummaryThree PRs address two related backend-skin startup failures: #71447 and #76648 both restore a previously persisted backend skin after delayed gateway registration, while #74018 adopts the backend-configured skin when a profile has no persisted Desktop preference and also corrects profile-scoped event routing. Related pull requests
Duplicates#71447 and #76648 address the same #71446 restart failure through competing implementations; treat #71447 as superseded by and duplicate of #76648. #74018 is not a duplicate because it addresses first-use adoption for #73987 and broader profile-scoped synchronization. Suggested consolidationKeep #76648 open with a salvage path: preserve its registry-triggered persisted-skin re-resolution and focused regression test. Close #71447 as duplicate of #76648 because its known-name cache leaves the contributor-identified junk-value and profile/runtime-plugin gaps unresolved, despite its keep_open review. Keep #74018 open separately for #73987, retaining its preference-presence guard and profile-scoped synchronization and routing work. Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I71446(["issue #71446 (open)"])
subgraph Dup71447 ["PRs duplicating each other"]
P71447["PR #71447 (open)"]
P76648["PR #76648 (open)"]
end
P76648 -->|best fix| I71446
class I71446 open
class P71447 open
class P76648 open
class P71447 best
class P76648 best
class P76648 target
click I71446 "https://github.com/NousResearch/hermes-agent/issues/71446"
click P71447 "https://github.com/NousResearch/hermes-agent/pull/71447"
click P76648 "https://github.com/NousResearch/hermes-agent/pull/76648"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 3 pull requests and 2 issues in this complex. Each diff was read against this issue; Assessment working set: 49 kB of PR diffs, 12 kB of issue/PR text, 7 kB of discussion (7 comments), 7 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
What does this PR do?
Fixes the desktop app snapping back to the default theme on every restart when the chosen theme is a backend skin (a YAML skin under
$HERMES_HOME/skins, announced by the gateway, e.g.skin: catppuccininconfig.yaml).Root cause: backend skins are announced on
gateway.ready, which fires after the ThemeProvider has already resolved the persisted theme choice. At that pointnormalizeSkincan't resolve the stored name yet, so it falls back to the default. Nothing re-reads the persisted choice once the skin registers, so the user's pick is stored but never painted again.The fix re-reads the persisted skin whenever the backend theme registry grows and adopts it when it resolves to something we're not already showing. A functional
setStatekeeps reference identity on the no-op path, so unrelated registry churn doesn't re-render the themed tree.Related: #75374 fixes the same class of bug for plugin-contributed themes (contrib registry). This PR covers the backend-skin store; the two registries don't overlap.
Related Issue
No issue filed — found while debugging on Fedora. Searched open PRs before opening; #75374 is the closest existing one and covers the contributed-theme path, not backend skins.
Type of Change
Changes Made
apps/desktop/src/themes/context.tsx: new effect keyed onbackendThemes+profileKeythat re-resolves the persisted skin name whenever the backend registry growsapps/desktop/src/themes/context.test.tsx: regression test reproducing the race (persisted backend skin → boot falls back to default → gateway seed registers the skin → assert repaint)How to Test
Reproduction: set
skin: catppuccin(or any skin in$HERMES_HOME/skins) inconfig.yaml, pick it in Appearance, restart the app. Without the fix the app paints the default on every launch; with it the choice sticks.Verification done:
mainwithout the fix, passes with it (red-green confirmed)Platform tested: Fedora 44 x86_64, packaged Electron build.
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass — N/A: change is in the desktop app (TypeScript); ran the vitest themes suite instead (8 files / 67 tests green)Documentation & Housekeeping
Notes
Authored with AI assistance (Hermes Agent); the diff, reproduction, and test were verified manually before submitting.