Release LP — v0.51.352 (medium round: jump-to-response, STATE_DIR warning, J/K nav)#3948
Conversation
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>
|
| 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)"]
Comments Outside Diff (1)
-
static/sessions.js, line 6272-6279 (link)Missing
e.repeatguard — rapid session cycling on held keyThe
keydownevent fires continuously when a key is held; without ane.repeatcheck, keeping 'j' or 'k' depressed firesloadSessionon 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. Addingif(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
| 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; |
There was a problem hiding this comment.
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.
| 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!
Release LP — v0.51.352 (Phase 2 medium round)
Three medium-risk fixes, each rebased onto fresh master, full-suite + Codex + Opus gated.
Shipped
getClientRects().length>0) so a folded-Worklog turn whose first segment is hidden (assistant-segment-worklog-source/-anchor, display:none) no longer suppresses the question-row fallback. All 13 locales. Closes UX: 'jump to question' should jump to response start, not the user prompt #3852.Gate results
-p no:xdist).Note: both advisors independently caught the same #3934 hidden-segment bug — strong corroboration of the gate.