# Track Specification: Cache Analytics Display (cache_analytics_20260306) ## Overview Gemini cache hit/miss visualization, memory usage, TTL status display. Uses existing `ai_client.get_gemini_cache_stats()` which is implemented but has no GUI representation. ## Current State Audit ### Already Implemented (DO NOT re-implement) - **`ai_client.get_gemini_cache_stats()`** (src/ai_client.py) - Returns dict with: - `cache_exists`: bool - Whether a Gemini cache is active - `cache_age_seconds`: float - Age of current cache in seconds - `ttl_seconds`: int - Cache TTL (default 3600) - `ttl_remaining`: float - Seconds until cache expires - `created_at`: float - Unix timestamp of cache creation - **Gemini cache variables** (src/ai_client.py lines ~60-70): - `_gemini_cache`: The `CachedContent` object or None - `_gemini_cache_created_at`: float timestamp when cache was created - `_GEMINI_CACHE_TTL`: int = 3600 (1 hour default) - **Cache invalidation logic** already handles 90% TTL proactive renewal ### Gaps to Fill (This Track's Scope) - No GUI panel to display cache statistics - No visual indicator of cache health/TTL - No manual cache clear button in UI - No hit/miss tracking (Gemini API doesn't expose this directly - may need approximation) ## Architectural Constraints ### Threading & State Access - **Non-Blocking**: Cache queries MUST NOT block the UI thread. The `get_gemini_cache_stats()` function reads module-level globals (`_gemini_cache`, `_gemini_cache_created_at`) which are modified on the asyncio worker thread during `_send_gemini()`. - **No Lock Needed**: These are atomic reads (bool/float/int), but be aware they may be stale by render time. This is acceptable for display purposes. - **Cross-Thread Pattern**: Use `manual-slop_get_git_diff` to understand how other read-only stats are accessed in `gui_2.py` (e.g., `ai_client.get_comms_log()`). ### GUI Integration - **Location**: Add to `_render_token_budget_panel()` in `gui_2.py` or create new `_render_cache_panel()` method. - **ImGui Pattern**: Use `imgui.collapsing_header("Cache Analytics")` to allow collapsing. - **Code Style**: 1-space indentation, no comments unless requested. ### Performance - **Polling vs Pushing**: Cache stats are cheap to compute (just float math). Safe to recompute each frame when panel is open. - **No Event Needed**: Unlike MMA state, cache stats don't need event-driven updates. ## Architecture Reference Consult these docs for implementation patterns: - **[docs/guide_architecture.md](../../../docs/guide_architecture.md)**: Thread domains, cross-thread patterns - **[docs/guide_tools.md](../../../docs/guide_tools.md)**: Hook API if exposing cache stats via API ### Key Integration Points | File | Lines | Purpose | |------|-------|---------| | `src/ai_client.py` | ~200-230 | `get_gemini_cache_stats()` function | | `src/ai_client.py` | ~60-70 | Cache globals (`_gemini_cache`, `_GEMINI_CACHE_TTL`) | | `src/ai_client.py` | ~220 | `cleanup()` function for manual cache clear | | `src/gui_2.py` | ~1800-1900 | `_render_token_budget_panel()` - potential location | | `src/gui_2.py` | ~150-200 | `App.__init__` state initialization pattern | ## Functional Requirements ### FR1: Cache Status Display - Display whether a Gemini cache is currently active (`cache_exists` bool) - Show cache age in human-readable format (e.g., "45m 23s old") - Only show panel when `current_provider == "gemini"` ### FR2: TTL Countdown - Display remaining TTL in seconds and as percentage (e.g., "15:23 remaining (42%)") - Visual indicator when TTL is below 20% (warning color) - Note: Cache auto-rebuilds at 90% TTL, so this shows time until rebuild trigger ### FR3: Manual Clear Button - Button to manually clear cache via `ai_client.cleanup()` - Button should have confirmation or be clearly labeled as destructive - After clear, display "Cache cleared - will rebuild on next request" ### FR4: Hit/Miss Estimation (Optional Enhancement) - Since Gemini API doesn't expose actual hit/miss counts, estimate by: - Counting number of `send()` calls while cache exists - Display as "Cache active for N requests" ## Non-Functional Requirements | Requirement | Constraint | |-------------|------------| | Frame Time Impact | <1ms when panel visible | | Memory Overhead | <1KB for display state | | Thread Safety | Read-only access to ai_client globals | ## Testing Requirements ### Unit Tests - Test panel renders without error when provider is Gemini - Test panel is hidden when provider is not Gemini - Test clear button calls `ai_client.cleanup()` ### Integration Tests (via `live_gui` fixture) - Verify cache stats display after actual Gemini API call - Verify TTL countdown decrements over time ### Structural Testing Contract - **NO mocking** of `ai_client` internals - use real state - Test artifacts go to `tests/artifacts/` ## Out of Scope - Anthropic prompt caching display (different mechanism - ephemeral breakpoints) - DeepSeek caching (not implemented) - Actual hit/miss tracking from Gemini API (not exposed) - Persisting cache stats across sessions ## Acceptance Criteria - [ ] Cache panel displays in GUI when provider is Gemini - [ ] Cache age shown in human-readable format - [ ] TTL countdown visible with percentage - [ ] Warning color when TTL < 20% - [ ] Manual clear button works and calls `ai_client.cleanup()` - [ ] Panel hidden for non-Gemini providers - [ ] Uses existing `get_gemini_cache_stats()` - no new ai_client code - [ ] 1-space indentation maintained