hermes - ✅(Solved) Fix hermes-achievements lifetime counters regress after sessions.auto_prune prunes state.db [2 pull requests, 3 comments, 2 participants]

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…
GitHub stats
NousResearch/hermes-agent#28661Fetched 2026-05-20 04:02:44
View on GitHub
Comments
3
Participants
2
Timeline
8
Reactions
0
Author
Participants
Timeline (top)
commented ×3labeled ×3cross-referenced ×2

Root Cause

Once progress is earned, it should not regress just because old session rows were pruned.

Fix Action

Fixed

PR fix notes

PR #28705: fix(achievements): persist lifetime counters to prevent regression after prune

Description (problem / solution / changelog)

Problem

When sessions.auto_prune deletes old rows from state.db, achievement lifetime counters regress because they are recomputed only from remaining sessions (issue #28661).

Fix

Merge scanned aggregate counters with persisted lifetime_counters in state.json using max(). Once a counter reaches a value it never goes backward.

Fixes #28661

Changed files

  • gateway/platforms/email.py (modified, +47/-2)

PR #28713: fix(achievements): persist lifetime counters to prevent regression after prune

Description (problem / solution / changelog)

Problem

When sessions.auto_prune deletes old rows from state.db, achievement lifetime counters regress because they are recomputed only from remaining sessions (issue #28661).

Fix

Merge scanned aggregate counters with persisted lifetime_counters in state.json using max(). Once a counter reaches a value it never goes backward — pruning state.db cannot reduce lifetime achievements.

Fixes #28661

Changed files

  • plugins/hermes-achievements/dashboard/plugin_api.py (modified, +17/-0)

Code Example

unlocked_count: 57
discovered_count: 3
total_count: 60
scan_meta.mode: full
sessions_scanned_so_far: 522
sessions_expected_total: 522

---

plugins/hermes-achievements/dashboard/plugin_api.py

---

sessions_meta = db.list_sessions_rich(
    limit=db_limit,
    include_children=True,
    project_compression_tips=False,
)

---

return {
    "sessions": sessions,
    "aggregate": aggregate_stats(sessions),
    ...
}

---

counter = max(persisted_counter, scanned_counter)

---

~/.hermes/sessions/
RAW_BUFFERClick to expand / collapse

Bug

hermes-achievements lifetime progress regresses after session pruning.

A → B:

  • sessions.auto_prune=true
  • old rows are deleted from ~/.hermes/state.db
  • hermes-achievements recomputes lifetime counters from SessionDB.list_sessions_rich()
  • lifetime achievements lose history
  • unlocked/discovered state can move backward

This makes session pruning incompatible with lifetime achievements.

Repro / observed data

Environment:

  • Hermes Agent: v0.14.0 (2026.5.16)
  • Dashboard achievements plugin: bundled hermes-achievements
  • DB: ~/.hermes/state.db

Before prune / from backup:

  • sessions: 516+
  • achievements: 57/60

After sessions.retention_days=14 prune + VACUUM:

  • sessions: 350–354
  • achievements: 54/60

After merging the pre-prune DB backup back into current DB:

  • sessions: 522
  • messages: 36801
  • achievements: 57/60
  • scan: 522/522
  • is_stale=false

Example restored scan output:

unlocked_count: 57
discovered_count: 3
total_count: 60
scan_meta.mode: full
sessions_scanned_so_far: 522
sessions_expected_total: 522

Current code path

Relevant file:

plugins/hermes-achievements/dashboard/plugin_api.py

The scan path uses SessionDB:

sessions_meta = db.list_sessions_rich(
    limit=db_limit,
    include_children=True,
    project_compression_tips=False,
)

Then lifetime counters are recomputed from the scanned sessions:

return {
    "sessions": sessions,
    "aggregate": aggregate_stats(sessions),
    ...
}

So if pruned sessions are no longer in state.db, lifetime achievement counters drop.

Why this is a design bug

state.db sessions are operational history and can be pruned for performance.

Achievements are lifetime state and should be monotonic.

Those lifecycles conflict if achievements are recomputed only from the prunable sessions table.

Expected behavior

Session pruning should not reduce lifetime achievements.

Once progress is earned, it should not regress just because old session rows were pruned.

Possible fixes

Preferred:

Persist lifetime counters in ~/.hermes/plugins/hermes-achievements/state.json and merge with scanned values monotonically:

counter = max(persisted_counter, scanned_counter)

Then pruning state.db cannot reduce lifetime achievements.

Alternative:

Scan archived session files under:

~/.hermes/sessions/

But this needs careful dedupe across session_*.json, *.jsonl, WebUI sessions, cron/background sessions, etc.

Less ideal:

Hook session pruning to run achievements aggregation first, then persist counters before deleting old rows.

Risk

Users enabling session pruning or running VACUUM after prune can permanently lose achievement history unless they still have a state.db backup.

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…

FAQ

Expected behavior

Session pruning should not reduce lifetime achievements.

Once progress is earned, it should not regress just because old session rows were pruned.

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 - ✅(Solved) Fix hermes-achievements lifetime counters regress after sessions.auto_prune prunes state.db [2 pull requests, 3 comments, 2 participants]