5.0 KiB
Hermes Achievements Performance Spec (Post-Hackathon)
Status: Draft (no code changes yet)
Owner: hermes-achievements plugin
Scope: dashboard/plugin_api.py + dashboard/dist/index.js request behavior
Decision: Drop /overview and top-banner slots; keep only Achievements tab data path.
1) Problem Statement
Current plugin endpoints /achievements and /overview both execute a full history recomputation (evaluate_all()), which performs a full SessionDB scan each request.
Observed on this machine/repo:
- ~83 sessions
- ~7,125 messages
- ~3,623 tool calls
evaluate_all()~13–16s per call/achievements~13–15s per call/overview~12–15s per call- Overlap between endpoints increases perceived wait.
Given current product direction, /overview and cross-tab top-banner slots are not needed.
2) Goals
- Keep achievement correctness unchanged.
- Keep all Achievements-tab UX/data (unlocked/discovered/secrets/highest/latest/cards).
- Remove unused summary path (
/overview) and slot wiring. - Make Achievements tab faster by avoiding duplicate endpoint pathways.
- Ensure at most one heavy scan can run at a time.
Non-goals (phase 1):
- Rewriting achievement rules.
- Changing badge semantics/states.
3) Endpoint Semantics (Target)
GET /api/plugins/hermes-achievements/achievements
Single source endpoint for Achievements UI. Returns full payload used by the tab:
achievementsunlocked_countdiscovered_countsecret_counttotal_counterror
POST /api/plugins/hermes-achievements/rescan (optional)
Manual refresh trigger. Prefer async trigger + immediate status response.
GET /api/plugins/hermes-achievements/scan-status (optional new)
Reports scan state for UX/ops.
Removed
GET /api/plugins/hermes-achievements/overview
4) UI Scope (Target)
Keep:
- Achievements page/tab (
/achievementsin plugin tab manifest) - All existing Achievements tab stats/cards/filters
Remove:
- Top-banner summary slot components using
sessions:topandanalytics:top - Any frontend call path to
/overview
5) Runtime State Machine (for /achievements)
FRESH: cached snapshot age <= TTLSTALE: snapshot exists but expiredSCANNING: background recompute runningFAILED: last recompute failed, last good snapshot still served
Rules:
- FRESH -> serve immediately.
- STALE + not scanning -> serve stale snapshot immediately and launch background refresh.
- SCANNING -> do not start another scan; join single-flight in-flight job.
- No snapshot yet -> allow one blocking bootstrap scan.
6) Caching & Invalidation
Phase 1
- In-memory cache + persisted snapshot file.
- TTL: 60–180 seconds (configurable).
- Single-flight dedupe for scan requests.
- Persist plugin data under:
~/.hermes/plugins/hermes-achievements/scan_snapshot.json
Phase 2
- Incremental scan checkpoints with per-session fingerprints.
- Persist checkpoint data under:
~/.hermes/plugins/hermes-achievements/scan_checkpoint.json
- Checkpoint stores, per session:
session_id- fingerprint (
updated_at, message_count, or hash) - cached per-session contribution used for aggregate recomposition
- Scan policy:
- First run: full scan and materialize snapshot + checkpoint.
- Next runs: process only new/changed sessions, reuse unchanged contributions.
- Full rebuild only on:
- schema/version change
- checkpoint corruption
- explicit full rescan
7) Frontend Contract
- Achievements tab requests
/achievementsonce on mount. - No slot-based summary fetches.
- If response says
is_stale=true, UI may display “Updating in background”. - Avoid duplicate mount-triggered calls and cancel stale requests on navigation.
8) SLO Targets
/achievementsp95 < 1s (cached)- Max concurrent heavy scans: 1
- Background refresh should not block UI
9) Observability Requirements
Track:
- scan count
- scan duration avg/p95
- dedupe hit count (joined in-flight scans)
- stale-served count
- failures + last error
Expose minimal diagnostics in /scan-status.
10) Backward Compatibility
- Keep
/achievementsresponse shape backward-compatible. - Removing
/overviewis acceptable because slot UI is intentionally removed. - If temporary compatibility is needed,
/overviewcan return static deprecation response for one release.
11) Risks
- Stale data confusion -> mitigate with
generated_atand explicit refresh status. - Cache invalidation bugs -> start with conservative TTL + manual rescan.
- Concurrency bugs -> protect scan section with lock/single-flight guard.
- Session mutation edge cases -> use per-session fingerprint invalidation (not global timestamp only).
12) Persistence Files (Explicit)
Plugin state directory:
~/.hermes/plugins/hermes-achievements/
Files:
state.json(existing): unlock trackingscan_snapshot.json(new): latest materialized achievements payloadscan_checkpoint.json(new): per-session fingerprints + contributions for incremental refresh