Skip to content

[Hermes][Fork UI Recovery][hermes-fork-ui-features-port-v0182][1/n] Restore live context, bulk actions, and fluid drag - #283

Merged
OmarB97 merged 18 commits into
mainfrom
fix/hermes-fork-ui-features-port-v0182
Jul 15, 2026
Merged

[Hermes][Fork UI Recovery][hermes-fork-ui-features-port-v0182][1/n] Restore live context, bulk actions, and fluid drag#283
OmarB97 merged 18 commits into
mainfrom
fix/hermes-fork-ui-features-port-v0182

Conversation

@OmarB97

@OmarB97 OmarB97 commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Why

The v0.18.2 fork rebase dropped or disconnected several established Hermes Desktop behaviors: live per-session context usage, bulk session operations, reliable /compress, and natural cross-lane session reordering. Follow-up installed builds restored most of the surface, but bulk archive still crashed because two Python methods shared the same name, while drag previews applied both dnd-kit and Motion transforms to the same rows. That left the installed app with a nonfunctional archive action and a sluggish, visually imprecise drag response.

What changed

  • Restored the live color-coded context meter between turns, during token streaming, across focused-session switches, and hid it for an uncommitted New session draft.
  • Restored shared Pinned ↔ Sessions drag previews, pointer-release settlement, persisted order, packaged-Electron sensor activation, and anchor-relative insertion.
  • Removed double-applied drag transforms: the lifted row now follows the pointer directly while displaced siblings use one critically damped layout spring.
  • Restored Finder-style multi-row selection plus bulk prompt, steer, stop, pin, archive, and delete operations.
  • Restored /compress auto-interrupt and bounded busy retry behavior.
  • Split ID-based archive batching from filter-based archival, made archive batches atomic and compression-lineage aware, and resolved selected/pinned lineage aliases in the desktop store.

How to review

  1. Start with apps/desktop/src/lib/token-usage.ts, apps/desktop/src/app/session/hooks/use-session-state-cache.tsx, and the status-bar hook for the focused-session context contract.
  2. Review apps/desktop/src/app/chat/sidebar/shared-session-dnd.ts, reorderable-list.tsx, and session-row.tsx together; dnd-kit owns only the active row's pointer transform and Motion owns sibling slot transitions.
  3. Review apps/desktop/src/store/sidebar-selection.ts, selection-action-bar.tsx, and the session bulk action modules as one multi-row workflow.
  4. Review hermes_state.py::archive_session_ids and its lineage resolver beside the endpoint and transaction regression tests.
  5. Finish with the prompt-action slash handling and gateway protocol changes for /compress.

Evidence

  • Packaged Electron drag matrix: 16/16 exact placements across Pinned reorder, Sessions reorder, Sessions → first Pinned slot, and Pinned → interior Sessions slot; 0 active rows carried both transform systems.
  • Disposable packaged-app Archive all: confirmation checked 18 visible sessions, toast reported Archived 18 sessions, SQLite reported archived=1 | count=18, and all rows remained absent after reload.
  • Disposable packaged-app multi-select: two checked rows produced Archived 2 sessions; SQLite showed those two archived and the third still unarchived.
  • Installed /Applications/Hermes.app: idle context switched from 131.3k/200k [66%] to 16k/131.1k [12%], then New session removed the meter on the first rendered frame.
  • Installed renderer audit: correct file:///Applications/Hermes.app/... page, no blocking dialog, original meshboard-operator profile restored, and zero console/log entries at the final audit.
  • The installed app passed codesign --verify --deep --strict; the replaced build is retained as a timestamped rollback bundle.

Verification

  • PASS — scripts/run_tests.sh tests/test_hermes_state.py -q: 357/357 tests.
  • PASS — scripts/run_tests.sh tests/hermes_cli/test_web_server.py -q -k 'archive or bulk': 17/17 selected tests.
  • PASS — targeted desktop Vitest suite for bulk archive, shared drag, sortable bindings, and session rows: 30/30 tests.
  • PASS — npm run typecheck --workspace apps/desktop.
  • PASS — npm run lint --workspace apps/desktop -- --quiet.
  • PASS — python -m py_compile hermes_state.py.
  • PASS — signed production package built from clean commit 10ba19459ebaaba260ee4ae8087b44cbca93dd73 and installed successfully.

Risks / gaps

  • The app delegates backend behavior to ~/.hermes/hermes-agent; the installed runtime therefore received the exact tested hermes_state.py patch as well as the signed Desktop bundle. Existing unrelated local edits in hermes_cli/inventory.py and tui_gateway/server.py were preserved.
  • Packaging is development-signed but not notarized because the Apple notarization API credentials are not configured in this environment.
  • The broad unscoped Desktop Vitest command is intentionally not used because it discovers packaged release/ native dependency suites; the changed interaction paths have focused source tests plus packaged-app end-to-end proof.
  • The operator-disabled Hermes auto-update job remains disabled; re-enabling it is outside this recovery PR.

Collaborators

Participants:

  • @OmarB97 — operator on ko-mac
  • Codex (GPT-5) — implementation, packaged-app diagnostics, and verification on ko-mac

Process:

  • Time to finish: approximately 1 hour across iterative installed-app reports
  • Iteration: installed-app reproduce → source regression tests → signed disposable validation → controlled live install
  • Lead reviewer: @OmarB97

Task context:

  • Task: hermes-fork-ui-features-port-v0182
  • Feature: hermes-desktop-fork-feature-recovery-20260616
  • Size: L · Risk: medium · Priority: High

Related work:

  • Commits: a1d7990e20 through 10ba19459e
  • Rollback app: Hermes-05d11c0e5f-20260714-203000.app

Omar Baradei and others added 18 commits July 14, 2026 16:56
Re-authors PR NousResearch#43661 onto current main. Since the original PR, the sidebar
session section was extracted into sessions-section.tsx and the row into the
primitive chrome (SidebarRowShell/Body/Grab/Lead), so the original section and
row edits no longer applied; this rebuilds the feature on the current shape.

Native drag-and-drop for sidebar session rows: drag a row body onto Pinned to
pin it, drag a pinned row onto Sessions to unpin, and drag within either section
to reorder — with a live motion.div FLIP preview that animates the row shuffle
before the drop commits. The grab-handle dnd-kit reorder is retained alongside.

- inline-refs: the session drag payload carries pinId + pinned, plus a
  pinned-marker MIME so dragover can filter by pin-state before the payload is
  readable at drop.
- use-session-drop-zone (new): hook + helpers — anchor resolution with a
  dead-band hysteresis, preview splicing, and pin/unpin/reorder drop handling.
- session-row: the row body is the native drag source with a stable
  data-session-id hit-test anchor, wrapping a motion.div layout="position"
  visual so rects stay put while the preview animates.
- sessions-section / virtual-session-list: thread the drag callbacks and the
  drop-zone frame (dropActive highlight + handlers) through the extracted
  section.
- index: pinned/sessions drop zones wired to pinSession(id, index) and the flat
  session-order store; sessionByAnyId, messaging, and recents counts now account
  for pinned rows the sections no longer render.

pinSession(id, index) replaces the original PR's undefined reorderPinnedSession:
insertUniqueId already filters an existing pin out before re-inserting at the
given index, so one call serves both pin and pin-reorder.

Drag interactions can't be exercised headlessly; typecheck, build, lint, and the
21 drop-zone unit tests are green. Drag-to-pin/unpin/reorder and the FLIP
animation need manual QA in the running app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@OmarB97
OmarB97 merged commit d6e4757 into main Jul 15, 2026
26 of 36 checks passed
OmarB97 added a commit that referenced this pull request Jul 20, 2026
…estore live context, bulk actions, and fluid drag (#283)

* fix(desktop): restore live session context and bulk archive

* feat(desktop): refine sidebar session drag reordering

Re-authors PR NousResearch#43661 onto current main. Since the original PR, the sidebar
session section was extracted into sessions-section.tsx and the row into the
primitive chrome (SidebarRowShell/Body/Grab/Lead), so the original section and
row edits no longer applied; this rebuilds the feature on the current shape.

Native drag-and-drop for sidebar session rows: drag a row body onto Pinned to
pin it, drag a pinned row onto Sessions to unpin, and drag within either section
to reorder — with a live motion.div FLIP preview that animates the row shuffle
before the drop commits. The grab-handle dnd-kit reorder is retained alongside.

- inline-refs: the session drag payload carries pinId + pinned, plus a
  pinned-marker MIME so dragover can filter by pin-state before the payload is
  readable at drop.
- use-session-drop-zone (new): hook + helpers — anchor resolution with a
  dead-band hysteresis, preview splicing, and pin/unpin/reorder drop handling.
- session-row: the row body is the native drag source with a stable
  data-session-id hit-test anchor, wrapping a motion.div layout="position"
  visual so rects stay put while the preview animates.
- sessions-section / virtual-session-list: thread the drag callbacks and the
  drop-zone frame (dropActive highlight + handlers) through the extracted
  section.
- index: pinned/sessions drop zones wired to pinSession(id, index) and the flat
  session-order store; sessionByAnyId, messaging, and recents counts now account
  for pinned rows the sections no longer render.

pinSession(id, index) replaces the original PR's undefined reorderPinnedSession:
insertUniqueId already filters an existing pin out before re-inserting at the
given index, so one call serves both pin and pin-reorder.

Drag interactions can't be exercised headlessly; typecheck, build, lint, and the
21 drop-zone unit tests are green. Drag-to-pin/unpin/reorder and the FLIP
animation need manual QA in the running app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* style(desktop): satisfy restored feature lint

* style(desktop): fix named import order

* fix(desktop): restore packaged sidebar drag activation

* fix(desktop): restore continuous cross-section session drag

* fix(desktop): persist the rendered drag preview

* fix(desktop): commit sidebar drag on physical release

* fix(desktop): retain context usage between turns

* fix(desktop): honor persisted sidebar row order

* fix(desktop): ignore the active row during drop collision

* fix(desktop): preserve context window on warm resume

* fix(desktop): stabilize cross-lane drop anchors

* fix(desktop): retain session order through sidebar load

* fix(desktop): settle session drops at pointer release

* fix(desktop): restore session multi-select and reliable compress

* fix(desktop): repair bulk archive and session drag feel

* fix(desktop): persist profile session archives

---------

Co-authored-by: Omar Baradei <omar@kostudios.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant