Conflict resolution: both #1928 (session jump buttons) and #1929 (endless
scroll) add their own settings/UI/i18n keys. Resolved by keeping both —
the features are independent opt-in toggles.
Keep explicit bottom pins stable across late layout growth and make clicking the already-active sidebar session a no-op before loadSession mutates state. Update scroll regression tests for the delayed settle path.
PR #1854 added a math stash to _renderUserFencedBlocks so backslash LaTeX
delimiters (\[..\], \(..\)) survive esc() and reach the KaTeX renderer in
user bubbles. The stash ran BEFORE the existing code-fence stash, so a
user-typed code block containing LaTeX-like syntax was extracted as
KaTeX and rendered as math inside <pre><code>:
```
\[ a + b \] is wrong
```
→ <pre><code><div class="katex-block"> a + b </div> is wrong</code></pre>
renderMd() (assistant path) handles this correctly by running fence_stash
before math_stash. The user-bubble path got the order inverted. Fix:
stash code fences first, then run the math regexes on the
outside-of-fence text only. Both top-level math and code-fenced literals
now render correctly:
- "math: \[ x + y \]" → KaTeX block
- "```\n\[ a + b \]\n```" → literal <pre><code>\[ a + b \]</code></pre>
Adds two regression tests:
- test_user_code_block_with_latex_syntax_renders_as_literal_code
(fails pre-fix, asserts no KaTeX wrappers inside <pre><code>)
- test_user_bubble_top_level_latex_still_renders_after_fence_reorder
(sibling guard against over-correcting and disabling math entirely)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier in this branch I'd reduced .panel-header > span:first-child to
flex-shrink:1 thinking it would let heading + chip fit better at the
default 300px panel width. That broke
test_workspace_label_shrinks_with_ellipsis which pins the
git-badge:3 > label:2 > icons:0 shrink hierarchy as load-bearing
(git badge collapses first, label second, icons never).
The chip-on-narrow-panel concern is now addressed by the @container
query that hides the chip entirely below 420px container width — the
heading no longer competes with the chip for horizontal space, so
flex-shrink:2 is fine again.
The original specifier 'static/vendor/smd.min.js' was a bare module
specifier, which the [HTML spec](https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier)
rejects: relative ES module references must start with '/', './', or
'../'. The block failed silently, window.smd was never set, and live
streaming markdown was broken for all users.
Fix: change to './static/vendor/smd.min.js' — the './'-relative form
satisfies both the ES module spec AND keeps the import resolution
mount-agnostic, so subpath deployments like /hermes/ continue to work.
Tests test_smd_vendor_import_is_mount_agnostic and
test_static_vendor_import_is_relative_to_current_mount updated to
require the './' form and forbid both the bare-specifier and
root-absolute forms.
Adapted from PR #1851 by @ChaseFlorell. Original PR fix used the
root-absolute form which fixed the bare-specifier bug but broke
subpath deployments; the './' form is the only shape that satisfies
both constraints.
Co-authored-by: Chase Florell <ChaseFlorell@users.noreply.github.com>
At the default 300px panel width, even the icon-only chip + 'Workspace'
heading + 5 action buttons overflowed and triggered ellipsis on the
heading ('WORKSP...'). Cleaner: hide the chip below 420px container
width and rely on the kebab's accent dot as the non-default-state
signal. The dot costs zero horizontal space (absolute-positioned over
the kebab icon) and the kebab's tooltip still labels what's happening.
On wider panels (user-resized, or future layouts), the full chip with
text appears.
Vision review of v1 flagged the chip's accent-yellow as 'loud and ugly'.
Switched to muted hover-bg + 1px border for a subtler badge look. Also
addressed heading truncation: at the default 300px panel width, heading
(95px) + 5 action buttons (154px) + chip text (110px) overflows, so the
heading was ellipsing to 'W...'. Added a container query on the existing
.rightpanel container that drops the chip text below 360px container
width, leaving just the eye icon (tooltip still labels it).
Replaces the always-visible inline toggle row that ate ~32px below the
breadcrumb on every panel view (root, subdir, file preview). The toggle
is a set-once preference — most users flip it once or never — so the
control hides behind a kebab dropdown in the panel-actions row instead.
A small 'hidden visible' indicator next to the WORKSPACE heading flags
the non-default state so users don't forget the pref is on. Click the
indicator to reopen the menu and uncheck.
The localStorage key, filtering behavior, and the canonical
\`workspaceShowHiddenFiles\` checkbox id are unchanged — the checkbox
is rebuilt inside the dropdown each time it opens. All 11 existing
regression tests for #1793 stay green; 7 new tests pin the kebab
affordance shape.
PR #1828 added an await loadKanbanBoards() at the START of loadKanban() to
resolve the active board before board-scoped requests fire (so a stale saved
slug can fall back to default cleanly). The existing tail-of-function refresh
at line 1278 was harmless under one-time loads but doubles /api/kanban/boards
traffic under SSE-driven refreshes (debounced at 250ms via
_scheduleKanbanRefresh). The 30-second polling interval started by
_kanbanStartPolling() picks up any board state changes that arrive after
the render, so the tail call is redundant in PR #1828's new model.
Per Opus pre-release verdict: SHIP with this perf cleanup as in-release
absorb (5 LOC delta, clearly defensive, no behavior change for the
single-load case).