Skip to content

fix(dashboard): probe last_read_at in read-only session-store staleness check - #80401

Closed
wangyunyou wants to merge 1 commit into
NousResearch:mainfrom
wangyunyou:fix/probe-last-read-at
Closed

fix(dashboard): probe last_read_at in read-only session-store staleness check#80401
wangyunyou wants to merge 1 commit into
NousResearch:mainfrom
wangyunyou:fix/probe-last-read-at

Conversation

@wangyunyou

Copy link
Copy Markdown

Summary

The read-only session-store staleness probe (_SESSION_DB_READ_PROBE_SQL in hermes_cli/web_server.py) was not updated when last_read_at landed in ec0c8d9c2 ("feat(state): sessions carry read/unread state").

Read-only opens skip _reconcile_columns() (by design), so an older store missing only that column passes the probe — archived / pinned / active / compacted all exist — and never triggers the heal-once writable open. Every GET /api/sessions poll then 500s with no such column: s.last_read_at until something opens the store writable (CLI/gateway startup). Profiles used only through the desktop/dashboard backend never get that writable open, so their session lists stay broken indefinitely.

Reproduction

On a profile whose state.db predates ec0c8d9c2 (sessions table without last_read_at):

  1. Desktop sidebar polls GET /api/sessions → 500 on every poll (once per ~60s)
  2. Logs: hermes_cli.web_server: GET /api/sessions failedsqlite3.OperationalError: no such column: s.last_read_at (traceback in list_sessions_rich, hermes_state.py:6055)
  3. The stale-schema heal in _open_session_db_for_profile never fires because the probe SQL doesn't reference the missing column, so the store stays read-only forever

Observed on a real install: two profiles (xuanru, money) created Aug 2 with stores missing last_read_at; both session lists 500'd from the moment the update landed until a CLI run opened the store writable.

Fix

Add (SELECT last_read_at FROM sessions LIMIT 1) to the probe. A store missing the column now fails the probe, which triggers the existing one-time writable open; _init_schema()_reconcile_columns() then adds the column declaratively (no version-gated migration needed).

Test Plan

  • scripts/run_tests.sh tests/hermes_cli/test_web_server.py tests/test_web_server_sessiondb_eventloop.py -q142 passed, 0 failed
  • E2E against a real pre-update state.db snapshot (missing last_read_at):
    • probe now raises no such column: last_read_at
    • writable SessionDB open adds the column (53 cols) ✅
    • re-probe passes, list_sessions_rich(limit=3) returns rows ✅

…ss check

The read-only stale-schema probe (compiled against the columns the
dashboard read paths query) missed last_read_at when it landed in
ec0c8d9. Read-only opens skip _reconcile_columns(), so a store missing
only that column passes the probe, never heals through the one-time
writable open, and 500s on every /api/sessions poll until a CLI/gateway
startup opens it writable — profiles used only via desktop/dashboard
stay broken indefinitely.
@alt-glitch alt-glitch added type/bug Something isn't working comp/dashboard Web dashboard / control panel UI (dashboard/, landing) area/sessions Session lifecycle, resume, persistence, history P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Aug 6, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #80047. Both patches add last_read_at to the same read-only session-store probe; #80047 is the earlier open fix and also includes the regression test.

@OutThisLife

Copy link
Copy Markdown
Collaborator

Closing as implemented on main.

#80797 (merged, bdee48928) replaced the hand-written probe with _session_db_read_probe_statements(), derived from SCHEMA_SQL via schema_read_probe_statements() — so last_read_at and every future column are covered automatically. The _SESSION_DB_READ_PROBE_SQL constant this patches no longer exists on main.

Your diagnosis was right, and it's the fix that landed — just generalized so the probe can't go stale again the next time a column ships. Thanks for chasing it down.

@OutThisLife OutThisLife closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/dashboard Web dashboard / control panel UI (dashboard/, landing) duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants