hermes - 💡(How to fix) Fix bug: TUI resume listing hides message-bearing child sessions

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

The data was not lost: the message-bearing rows existed in state.db, but they were stored as child sessions. The TUI listing path was querying root sessions only, so Kanban worker sessions showed up because they are typically root rows, while normal delegated/compressed conversation transcripts were hidden under parent_session_id.

Fix Action

Fix / Workaround

Local Patch That Fixed It

This local patch fixed the issue for my DB by making the TUI listing/resume path include child sessions, order by last activity, avoid projecting through compression tips for this raw picker query, and filter out zero-message/internal tool rows.

Targeted test run after the local patch:

Code Example

diff --git a/tui_gateway/server.py b/tui_gateway/server.py
--- a/tui_gateway/server.py
+++ b/tui_gateway/server.py
@@
-        rows = [
-            s
-            for s in db.list_sessions_rich(source=None, limit=fetch_limit)
-            if (s.get("source") or "").strip().lower() not in deny
-        ][:limit]
+        rows = [
+            s
+            for s in db.list_sessions_rich(
+                limit=fetch_limit,
+                include_children=True,
+                project_compression_tips=False,
+                order_by_last_active=True,
+            )
+            if (s.get("source") or "").strip().lower() not in deny
+            and int(s.get("message_count") or 0) > 0
+        ][:limit]
@@
-        rows = db.list_sessions_rich(source=None, limit=200)
+        rows = db.list_sessions_rich(
+            limit=200,
+            include_children=True,
+            project_compression_tips=False,
+            order_by_last_active=True,
+        )
         for row in rows:
             src = (row.get("source") or "").strip().lower()
             if src in deny:
                 continue
+            if int(row.get("message_count") or 0) <= 0:
+                continue
             return _ok(

---

scripts/run_tests.sh tests/test_tui_gateway_server.py

---

187 tests passed, 0 failed
RAW_BUFFERClick to expand / collapse

Bug Description

The TUI historical session picker/resume path can hide message-bearing non-Kanban historical sessions while surfacing empty parent/compression shell rows. In my local state.db, Kanban task sessions appeared correctly, but normal historical Hermes sessions showed no messages from the TUI history/resume surface.

The data was not lost: the message-bearing rows existed in state.db, but they were stored as child sessions. The TUI listing path was querying root sessions only, so Kanban worker sessions showed up because they are typically root rows, while normal delegated/compressed conversation transcripts were hidden under parent_session_id.

Symptoms

  • Kanban task sessions show up and have messages.
  • Other historical sessions appear empty / show no messages from the TUI picker/resume flow.
  • Inspecting state.db shows the actual messages are still present on child sessions.
  • Recent zero-message compression/coordination shell rows can be listed instead of the actual message-bearing child rows.

Expected Behavior

The TUI historical session picker / most-recent resume path should surface resumable, message-bearing user conversation sessions, including child sessions that contain the actual transcript.

Actual Behavior

The TUI path effectively surfaces root rows only. This can hide the real transcript rows and make it look like historical sessions have no messages.

Root Cause / Diagnosis

session.list and session.most_recent in tui_gateway/server.py call list_sessions_rich(...) without include_children=True. That excludes child sessions, even when those child sessions are the rows that contain the user-visible transcript.

Kanban can appear unaffected because Kanban worker sessions are often root sessions with their messages directly attached.

This seems related to the broader lineage/session visibility issues discussed in:

  • #34647
  • #10374
  • #12960
  • #15745
  • #22203

Local Patch That Fixed It

This local patch fixed the issue for my DB by making the TUI listing/resume path include child sessions, order by last activity, avoid projecting through compression tips for this raw picker query, and filter out zero-message/internal tool rows.

diff --git a/tui_gateway/server.py b/tui_gateway/server.py
--- a/tui_gateway/server.py
+++ b/tui_gateway/server.py
@@
-        rows = [
-            s
-            for s in db.list_sessions_rich(source=None, limit=fetch_limit)
-            if (s.get("source") or "").strip().lower() not in deny
-        ][:limit]
+        rows = [
+            s
+            for s in db.list_sessions_rich(
+                limit=fetch_limit,
+                include_children=True,
+                project_compression_tips=False,
+                order_by_last_active=True,
+            )
+            if (s.get("source") or "").strip().lower() not in deny
+            and int(s.get("message_count") or 0) > 0
+        ][:limit]
@@
-        rows = db.list_sessions_rich(source=None, limit=200)
+        rows = db.list_sessions_rich(
+            limit=200,
+            include_children=True,
+            project_compression_tips=False,
+            order_by_last_active=True,
+        )
         for row in rows:
             src = (row.get("source") or "").strip().lower()
             if src in deny:
                 continue
+            if int(row.get("message_count") or 0) <= 0:
+                continue
             return _ok(

I also updated the affected session.most_recent tests to account for the new list_sessions_rich(...) kwargs and message_count filtering.

Verification

Targeted test run after the local patch:

scripts/run_tests.sh tests/test_tui_gateway_server.py

Result:

187 tests passed, 0 failed

Notes

I am opening this as an issue instead of a PR because I do not want to bikeshed the larger /sessions vs /resume product semantics right now. The narrow bug is that the TUI historical/resume path should not hide message-bearing child sessions while surfacing empty shell rows.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix bug: TUI resume listing hides message-bearing child sessions