Skip to content

Release v0.51.765 — Wave 1 batch (#5276 #5274 #5272 #5256 #5254 #5257) - #5277

Merged
nesquena-hermes merged 25 commits into
masterfrom
release/stage-w1
Jun 30, 2026
Merged

nesquena-hermes merged 25 commits into
masterfrom
release/stage-w1

Conversation

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Release v0.51.765 — Wave 1 batch (6 fix-class PRs)

Batched release of 6 gate-certified, file-disjoint contributor fix PRs. Each was individually
gate-certified GREEN (Codex SAFE + full suite + per-PR tests) at its current head; this combined
stage was re-gated as a unit.

Included

Gate

  • Files are disjoint across the 6 PRs (no shared-file overlap → no silent semantic conflict).
  • Combined-stage Codex regression gate: SAFE TO SHIP (no regression, core flows intact).
  • Full pytest suite: 11128 passed, 82 skipped, 1 xfailed, 2 xpassed. The only 2 "failures" are
    the pre-existing test_scheduled_jobs_profile_isolation.py serial-ordering artifact (passes
    12/12 in isolation; no PR here touches cron code) — environmental, not a regression.
  • ESLint runtime gate CLEAN, ruff forward gate CLEAN, node --check clean on all touched JS.

CHANGELOG updated under [Unreleased] → Fixed with per-author credit.

rodboev and others added 25 commits June 29, 2026 22:23
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
…o franksong2702/fix-transparent-live-snapshot

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Extract _turn_transcript_lacks_final_assistant_answer() so settlement
logic can inspect an already-merged transcript. The merge wrapper now
delegates to the pure evaluator without changing behavior.

Fixes #5141
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Batched release of 6 gate-certified fix PRs covering unread-badge correctness after compaction, CLI-to-WebUI session continuity, transparent-streaming live anchor ordering, optimistic sidebar deletion, settings-search dropdown overflow, and a behavior-preserving refactor of the terminal-failure transcript evaluator.

  • Unread badge / viewed sync (fix(#5273): sync active viewed count on done settle #5276): Computes a unified completedMessageCount from a 4-level fallback chain and advances _markSessionViewed to fire before the sidebar cache update, preventing a stale unread dot on the actively-viewed session after compaction.
  • CLI-origin WebUI continuity (fix(#5270): preserve first WebUI continuation context for CLI sessions #5274): Adds _session_messages_have_prefix to detect when a sidecar's context-messages are a proper prefix of the live CLI transcript, then refreshes session.messages on chat-start so the stitched CLI history is authoritative for the first WebUI follow-up; the compaction/compression-anchor path is preserved.
  • Transparent Streaming live anchor ordering (Fix Transparent Streaming live anchor scene replay #5257): Dispatches renderLiveAnchorActivityScene to a new _renderLiveAnchorActivitySceneTransparent renderer before the compact-only guard, idempotently replacing legacy live surfaces via data-anchor-scene attributes, and guards data-anchor-settled-scene-row to settled-only nodes so live rows no longer masquerade as final anchors.

Confidence Score: 4/5

Safe to merge; all six changes are narrowly scoped, file-disjoint, and backed by targeted tests covering the specific failure scenarios they fix.

The Python-side changes (models, routes, streaming) are straightforward and thoroughly tested with integration-style fixtures. The JS-side transparent-stream renderer (_renderLiveAnchorActivitySceneTransparent) is the most intricate change — ~70 lines of sequential DOM mutations whose correctness depends on selector ordering and attribute stamping that unit tests approximate with a custom FakeElement harness rather than a real browser. The logic reads correctly and the idempotency test passes, but live/final anchor ordering in a real browser session is inherently harder to verify statically than the backend changes.

static/ui.js — the new transparent live renderer and its interaction with the existing compact renderer; worth a quick smoke-test in a transparent-streaming session after merging.

Important Files Changed

Filename Overview
api/models.py Adds _session_messages_have_prefix helper and expands reconciled_state_db_messages_for_session to prefer the longer authoritative CLI transcript over a stale sidecar context prefix on the first WebUI continuation; compression-anchor path is preserved when the CLI override is not triggered.
api/routes.py Adds refresh_cli_messages keyword arg to _get_or_materialize_session; when True and the session is a CLI session, refreshes messages from get_cli_session_messages if the DB copy is a prefix-compatible superset of the sidecar. _handle_chat_start passes this flag, and test mocks updated to accept **kwargs.
api/streaming.py Behavior-preserving refactor: extracts _turn_transcript_lacks_final_assistant_answer (operates on an already-merged transcript) and makes _merged_transcript_lacks_final_assistant_answer a thin delegating wrapper that first merges then delegates; original signature and semantics unchanged.
static/messages.js Computes unified completedMessageCount via a 4-level fallback (payload count → payload messages.length → S.session.message_count → S.messages.length) and advances _markSessionViewed to fire before the sidebar cache update so the actively-viewed session never shows a stale unread dot after compaction.
static/ui.js Adds _renderLiveAnchorActivitySceneTransparent for transparent-stream live activity and dispatches to it before the compact-mode guard; conditionally stamps data-anchor-settled-scene-row (settled only) vs data-anchor-live-scene-row (live only) to prevent live rows from masquerading as final anchors. Complex DOM manipulation verified by idempotency tests.
static/sessions.js Context-menu Delete now passes an immediate ()=>Promise.resolve() beforeDelete hook through the existing deleteSession path so the sidebar row disappears optimistically instead of lingering until the slow server round-trip completes.
static/index.html Settings nav buttons wrapped in a new .settings-menu-items div to move scroll ownership off the parent #settingsMenu, allowing the absolutely-positioned search-results dropdown to escape the clip boundary.
static/style.css Sets #settingsMenu to overflow: visible and introduces .settings-menu-items as the scrollable flex column for nav buttons, enabling the search dropdown to overflow the panel boundary.
tests/test_issue5273_active_done_viewed_sync.py New Node.js-executed harness verifying all four fallback branches of completedMessageCount and confirming the pre-cache-update viewed sync for actively-viewed sessions across compaction scenarios.
tests/test_issue5270_cli_webui_continuity.py Four integration tests covering fresh materialization, claimed-sidecar refresh, chat-start flag propagation, and writability preservation for the CLI-to-WebUI continuity fix.
tests/test_live_to_final_anchor_visible_order.py Adds two new tests: a structural assertion verifying transparent dispatch precedes compact gate, and a Node.js-executed DOM test confirming idempotent render, legacy surface hiding, and correct attribute stamping for the transparent live renderer.
tests/test_issue5141_terminal_failure_transcript_evaluator.py New tests verifying the refactored evaluator split: both the direct _turn_transcript_lacks_final_assistant_answer path and the delegating wrapper produce identical results, and the wrapper's delegation is verified via mock patching.
tests/test_session_active_profile_authorization.py Two existing monkeypatches updated to accept **_kwargs on _get_or_materialize_session to stay compatible with the new refresh_cli_messages keyword argument.
tests/test_issue3975_cron_reply_materialization.py One-line update: materialize stub now accepts **_kwargs to accommodate the new keyword argument on _get_or_materialize_session.
tests/test_issue5250_settings_search_dropdown_escape.py New Playwright-based browser hit-test verifying the search results dropdown extends below #settingsMenu's visible boundary and is click-target-accessible.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI as Hermes CLI
    participant StateDB as state.db
    participant Routes as routes.py _handle_chat_start
    participant Materialize as _get_or_materialize_session
    participant Models as reconciled_state_db_messages
    participant Stream as _run_agent_streaming

    CLI->>StateDB: write turns (user + assistant)
    CLI->>Routes: WebUI chat-start (session_id)
    Routes->>Materialize: "sid, refresh_cli_messages=True"
    Materialize->>StateDB: get_cli_session_messages(sid)
    Note over Materialize: if latest >= current AND prefix matches<br/>s.messages = latest_messages
    Materialize-->>Routes: session (messages refreshed)
    Routes->>Models: reconciled_state_db_messages_for_session
    Note over Models: sidecar_messages = session.messages (refreshed)<br/>if sidecar longer than context_messages AND prefix OK<br/>local_messages = sidecar, skip compression path
    Models-->>Routes: merged history (CLI turns preserved)
    Routes->>Stream: _run_agent_streaming(conversation_history)
    Stream-->>Routes: result (CLI context intact)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI as Hermes CLI
    participant StateDB as state.db
    participant Routes as routes.py _handle_chat_start
    participant Materialize as _get_or_materialize_session
    participant Models as reconciled_state_db_messages
    participant Stream as _run_agent_streaming

    CLI->>StateDB: write turns (user + assistant)
    CLI->>Routes: WebUI chat-start (session_id)
    Routes->>Materialize: "sid, refresh_cli_messages=True"
    Materialize->>StateDB: get_cli_session_messages(sid)
    Note over Materialize: if latest >= current AND prefix matches<br/>s.messages = latest_messages
    Materialize-->>Routes: session (messages refreshed)
    Routes->>Models: reconciled_state_db_messages_for_session
    Note over Models: sidecar_messages = session.messages (refreshed)<br/>if sidecar longer than context_messages AND prefix OK<br/>local_messages = sidecar, skip compression path
    Models-->>Routes: merged history (CLI turns preserved)
    Routes->>Stream: _run_agent_streaming(conversation_history)
    Stream-->>Routes: result (CLI context intact)
Loading

Reviews (1): Last reviewed commit: "docs(changelog): wave-1 batch (#5276 #52..." | Re-trigger Greptile

@nesquena-hermes
nesquena-hermes merged commit 8d5ff4c into master Jun 30, 2026
17 checks passed
@nesquena-hermes
nesquena-hermes deleted the release/stage-w1 branch June 30, 2026 16:34
@cutter-sh

cutter-sh Bot commented Jun 30, 2026

Copy link
Copy Markdown

🎬 Cutter preview — PR #5277

/settings
/settings — Settings search surfaces matching options from every section in a single results list.

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

Labels

None yet

Projects

None yet

3 participants