Files
hermes-agent/plugins/hermes-achievements/docs/achievements-performance-spec.md
T
2026-06-14 14:30:48 -04:00

175 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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()` ~1316s per call
- `/achievements` ~1315s per call
- `/overview` ~1215s 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:
- `achievements`
- `unlocked_count`
- `discovered_count`
- `secret_count`
- `total_count`
- `error`
### `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 (`/achievements` in plugin tab manifest)
- All existing Achievements tab stats/cards/filters
Remove:
- Top-banner summary slot components using `sessions:top` and `analytics:top`
- Any frontend call path to `/overview`
---
## 5) Runtime State Machine (for `/achievements`)
- `FRESH`: cached snapshot age <= TTL
- `STALE`: snapshot exists but expired
- `SCANNING`: background recompute running
- `FAILED`: last recompute failed, last good snapshot still served
Rules:
1. FRESH -> serve immediately.
2. STALE + not scanning -> serve stale snapshot immediately and launch background refresh.
3. SCANNING -> do not start another scan; join single-flight in-flight job.
4. No snapshot yet -> allow one blocking bootstrap scan.
---
## 6) Caching & Invalidation
### Phase 1
- In-memory cache + persisted snapshot file.
- TTL: 60180 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 `/achievements` once 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
- `/achievements` p95 < 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 `/achievements` response shape backward-compatible.
- Removing `/overview` is acceptable because slot UI is intentionally removed.
- If temporary compatibility is needed, `/overview` can return static deprecation response for one release.
---
## 11) Risks
- Stale data confusion -> mitigate with `generated_at` and 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 tracking
- `scan_snapshot.json` (new): latest materialized achievements payload
- `scan_checkpoint.json` (new): per-session fingerprints + contributions for incremental refresh