Skip to content

Release LP — v0.51.352 (medium round: jump-to-response, STATE_DIR warning, J/K nav)#3948

Merged
nesquena-hermes merged 4 commits into
masterfrom
release/stage-p2
Jun 10, 2026
Merged

Release LP — v0.51.352 (medium round: jump-to-response, STATE_DIR warning, J/K nav)#3948
nesquena-hermes merged 4 commits into
masterfrom
release/stage-p2

Conversation

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Release LP — v0.51.352 (Phase 2 medium round)

Three medium-risk fixes, each rebased onto fresh master, full-suite + Codex + Opus gated.

Shipped

Gate results

Note: both advisors independently caught the same #3934 hidden-segment bug — strong corroboration of the gate.

nesquena-hermes and others added 4 commits June 10, 2026 19:48
The per-turn jump button now scrolls to the START OF THE RESPONSE (the assistant
segment) instead of the user's question, with a fail-safe fallback to the question
row when the assistant segment isn't found. Label updated to 'to response' across
all 13 locales.

Closes #3852.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
…e is empty

When SESSION_DIR has no session .json files and the index is empty/absent,
print_startup_config() now scans sibling state directories and prints a diagnostic
pointing the user at the populated sibling + the HERMES_WEBUI_STATE_DIR to set —
fully fail-safe (try/except, warning-only, no behavior change).

Closes #3915.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
…igation

Global j/k keydown bindings navigate the session list (j=next, k=prev), guarded
by _isInteractiveSwipeTarget so they never fire while typing in the composer or
any input/textarea/contenteditable. Modifier-key combos are ignored.

Closes #3845.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
@nesquena-hermes nesquena-hermes merged commit 64c5366 into master Jun 10, 2026
11 checks passed
@nesquena-hermes nesquena-hermes deleted the release/stage-p2 branch June 10, 2026 20:02
@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown

Greptile Summary

This release bundles three independent fixes rebased onto master: the per-turn jump button now scrolls to the first visible assistant segment (with a worklog-hidden-segment guard and question-row fallback), startup prints a diagnostic when the active state dir is empty but a sibling has session data, and vim-style J/K keys navigate the session list with modifier and editable-surface guards.

Confidence Score: 4/5

Safe to merge; all three changes are well-guarded with no behavioral side effects on the happy path.

All three features are well-contained: the startup warning is doubly fail-safe, the jump-to-response logic is correct with proper visibility and fallback handling, and the J/K listener is appropriately guarded. The only actionable gap is the missing e.repeat check — holding J or K will rapidly fire loadSession on every keydown repeat event, which is jarring UX but not a data-safety issue.

static/sessions.js — the J/K keydown listener would benefit from an e.repeat guard; everything else is straightforward.

Important Files Changed

Filename Overview
static/sessions.js Adds navigateSession() and a J/K keydown listener. Guard logic is sound (modifier keys + _isInteractiveSwipeTarget), but the handler doesn't filter e.repeat, so holding J or K will rapidly cycle through sessions.
api/config.py Adds _warn_state_dir_divergence() diagnostic: doubly wrapped in try/except, reads from correctly scoped warn variable, reports only the first sibling with session data, and makes no behavioral changes.
static/ui.js Extends jumpToTurnQuestion to accept an assistantRawIdx and scroll to the first visible assistant segment, with correct visibility guard (getClientRects().length>0) and proper fallback to the question-row path.
static/i18n.js Updates jump_to_question and jump_to_question_label strings across all 13 locales to reflect the new "to response" semantics; key names are unchanged.
tests/test_3845_keyboard_session_nav.py Source-level regression tests for J/K nav. end = SESSIONS_JS.index("}", start) + 1 relies on the function having no nested braces — fragile if the function is expanded, but adequate for the current implementation.
tests/test_issue2246_question_jump.py Updated existing tests for the new two-arg signatures and added two new tests: first-assistant-segment reverse-map construction, and the visible-segment guard with fallback.
tests/test_issue3915_state_dir_warning.py Comprehensive new test suite for STATE_DIR divergence warning; covers empty/null/{}/[] index variants, no-sibling paths, and multiple exception injection scenarios.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["keydown (j/k)"] --> B{e.repeat?}
    B -->|"(currently unguarded)"| C{modifier key?}
    B -->|"suggested: return"| Z["no-op"]
    C -->|yes| Z
    C -->|no| D{_isInteractiveSwipeTarget?}
    D -->|yes| Z
    D -->|no| E["e.preventDefault()\nnavigateSession(±1)"]
    E --> F["compute rows, sids, cur index"]
    F --> G{cur in list?}
    G -->|no| Z
    G -->|yes| H["clamp next index"]
    H --> I{next === cur?}
    I -->|yes| Z
    I -->|no| J["loadSession(next)"]

    K["jump button click"] --> L["jumpToTurnQuestion(qIdx, aIdx)"]
    L --> M{hasAssistant?}
    M -->|yes| N["querySelectorAll data-msg-idx=aIdx"]
    N --> O{visible segment\ngetClientRects>0?}
    O -->|yes| P["scrollIntoView start\nreturn true"]
    O -->|no — all hidden| Q["fall through to question row"]
    M -->|no| Q
    Q --> R{row in DOM?}
    R -->|yes| S["scrollIntoView center\nhighlightQuestionRow\nreturn true"]
    R -->|no| T{windowed history?}
    T -->|yes| U["expand window\nrenderMessages\nrAF → scrollToTarget"]
    T -->|no| V["return false (no-op)"]
Loading

Comments Outside Diff (1)

  1. static/sessions.js, line 6272-6279 (link)

    P2 Missing e.repeat guard — rapid session cycling on held key

    The keydown event fires continuously when a key is held; without an e.repeat check, keeping 'j' or 'k' depressed fires loadSession on every repeat event, rapidly cycling through every session in the list. While individually each call is safe, the effect is jarring and almost certainly not the intended UX. Adding if(e.repeat) return; after the modifier check prevents this.

Reviews (1): Last reviewed commit: "chore: stamp v0.51.352 — Release LP (med..." | Re-trigger Greptile

Comment thread static/sessions.js
Comment on lines +6184 to +6187
document.addEventListener('keydown',(e)=>{
if(e.key!=='j'&&e.key!=='k') return;
if(e.ctrlKey||e.metaKey||e.altKey) return;
if(typeof _isInteractiveSwipeTarget==='function'&&_isInteractiveSwipeTarget(e.target)) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Adding if(e.repeat) return; prevents the handler from firing on auto-repeated keydown events, so holding 'j' or 'k' won't rapidly cycle through every session in the list.

Suggested change
document.addEventListener('keydown',(e)=>{
if(e.key!=='j'&&e.key!=='k') return;
if(e.ctrlKey||e.metaKey||e.altKey) return;
if(typeof _isInteractiveSwipeTarget==='function'&&_isInteractiveSwipeTarget(e.target)) return;
document.addEventListener('keydown',(e)=>{
if(e.key!=='j'&&e.key!=='k') return;
if(e.repeat) return;
if(e.ctrlKey||e.metaKey||e.altKey) return;
if(typeof _isInteractiveSwipeTarget==='function'&&_isInteractiveSwipeTarget(e.target)) return;

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant