forked from Zakaria/hermes-agent
5.6 KiB
5.6 KiB
Hermes Achievements Implementation Spec (Detailed)
This document is implementation-facing detail to execute the performance refactor later.
Decision scope: keep only Achievements tab flow; remove /overview + top-banner slot integration.
A) Current Behavior Summary
evaluate_all()performs:- full
scan_sessions() SessionDB.list_sessions_rich(...)db.get_messages(session_id)for each session- text/tool regex analysis + aggregation + evaluation
- full
/overviewand/achievementsboth currently callevaluate_all()directly.- slot calls (
sessions:top,analytics:top) currently invoke/overview.
Consequence: repeated full recomputes and contention.
B) De-scope/Removal Changes
- Remove backend route:
GET /overview
- Remove frontend slot usage:
SummarySlotcomponentregisterSlot("sessions:top")registerSlot("analytics:top")
- Remove manifest slot declarations:
"slots": ["sessions:top", "analytics:top"]
- Keep:
- tab route/page for Achievements
/achievementsendpoint and full tab rendering
C) Target Internal Interfaces
1) SnapshotStore
Responsibilities:
- hold latest computed snapshot in memory
- persist/load snapshot from disk
- expose age and staleness checks
Storage path:
~/.hermes/plugins/hermes-achievements/scan_snapshot.json
Methods (conceptual):
get()-> snapshot | nullset(snapshot)is_stale(ttl_seconds)
2) ScanCoordinator
Responsibilities:
- single-flight guard for compute jobs
- track scan status
Methods:
run_if_needed(force: bool = false)get_status()
State fields:
state:idle|running|failedstarted_at,finished_atlast_errorrun_count
3) build_snapshot()
Responsibilities:
- execute current compute logic once
- on first run, perform full scan and materialize per-session contributions
- on subsequent runs, process only changed/new sessions via checkpoint fingerprints
- produce shape consumed by
/achievements
Output:
achievements- count fields
- optional
scan_meta
D) Endpoint Behavior Matrix (No /overview)
| Endpoint | Cache fresh | Cache stale | No cache | Force rescan |
|---|---|---|---|---|
/achievements |
return cached | return stale + trigger bg refresh | blocking bootstrap scan | n/a |
/rescan |
trigger refresh | trigger refresh | trigger refresh | yes |
/scan-status |
status only | status only | status only | status only |
Notes:
- At most one scan run active.
- Other callers either await same run or receive stale snapshot according to policy.
E) Data Shape (Proposed)
{
"generated_at": 0,
"is_stale": false,
"scan_meta": {
"duration_ms": 0,
"sessions_scanned": 0,
"messages_scanned": 0,
"mode": "full",
"error": null
},
"achievements": [],
"unlocked_count": 0,
"discovered_count": 0,
"secret_count": 0,
"total_count": 0,
"error": null
}
Compatibility guidance:
- Keep existing
/achievementskeys. - Add metadata keys without breaking old callers.
Checkpoint file (new):
~/.hermes/plugins/hermes-achievements/scan_checkpoint.json
Suggested checkpoint shape:
{
"schema_version": 1,
"generated_at": 0,
"sessions": {
"<session_id>": {
"fingerprint": {
"updated_at": 0,
"message_count": 0,
"hash": "optional"
},
"contribution": {
"metrics": {}
}
}
}
}
Notes:
- fingerprint mismatch => recompute that session contribution only.
- unchanged fingerprint => reuse stored contribution.
F) Concurrency Contract
- Any request path that needs fresh data must pass through single-flight coordinator.
- If a scan is running:
- do not start second scan
- either await in-flight run (bounded) or serve stale snapshot immediately
- lock scope must include scan start/finish state transitions.
G) Error Handling Contract
- If refresh fails and prior snapshot exists:
- return prior snapshot with
is_stale=trueand error metadata
- return prior snapshot with
- If refresh fails and no prior snapshot:
- return explicit error response (current behavior equivalent)
scan-statusshould always return last known state/error.
H) Frontend Integration Contract
- Achievements page:
- one fetch on mount to
/achievements - optional background refresh indicator if stale
- one fetch on mount to
- no top-banner slot integration
- avoid duplicate in-flight calls during fast navigation by cancellation/debounce.
I) Validation Checklist
/overviewroute removed- manifest has no
sessions:top/analytics:topslots - frontend has no
api("/overview")calls - repeated Achievements navigation does not create multiple heavy scans
- average warm load times meet SLOs
- unlock totals match pre-refactor baseline for same history
- no schema regression in
/achievementsresponse
J) Suggested File Placement for Future Work
- backend changes:
dashboard/plugin_api.py - optional extraction:
dashboard/perf_snapshot.pydashboard/perf_scan_coordinator.py
- frontend request hygiene:
dashboard/dist/index.js(or source if available) - plugin metadata:
dashboard/manifest.json - persisted runtime files:
~/.hermes/plugins/hermes-achievements/state.json(existing unlock state)~/.hermes/plugins/hermes-achievements/scan_snapshot.json(new)~/.hermes/plugins/hermes-achievements/scan_checkpoint.json(new)
K) Post-Implementation Reporting Template
Record:
- dataset size (sessions/messages/tool calls)
- pre/post
/achievementstimings (cold/warm) - whether single-flight dedupe triggered under repeated tab open
- any behavioral diffs in unlock counts