refinement of upcoming tracks

This commit is contained in:
2026-03-06 15:41:33 -05:00
parent 3ce6a2ec8a
commit fca40fd8da
24 changed files with 2388 additions and 391 deletions

View File

@@ -1,29 +1,144 @@
# Implementation Plan: Cache Analytics Display (cache_analytics_20260306)
## Phase 1: Cache Stats Integration
- [ ] Task: Initialize MMA Environment
- [ ] Task: Verify get_gemini_cache_stats
- WHERE: src/ai_client.py
- WHAT: Check existing function
- HOW: Review implementation
> **Reference:** [Spec](./spec.md) | [Architecture Guide](../../../docs/guide_architecture.md)
## Phase 1: Foundation & Research
Focus: Verify existing infrastructure and set up panel structure
- [ ] Task 1.1: Initialize MMA Environment
- Run `activate_skill mma-orchestrator` before starting
- [ ] Task 1.2: Verify ai_client.get_gemini_cache_stats()
- WHERE: `src/ai_client.py` lines ~200-230
- WHAT: Confirm function exists and returns expected dict structure
- HOW: Use `manual-slop_py_get_definition` on `get_gemini_cache_stats`
- OUTPUT: Document exact return dict structure in task notes
- [ ] Task 1.3: Verify ai_client.cleanup()
- WHERE: `src/ai_client.py` line ~220
- WHAT: Confirm function clears `_gemini_cache`
- HOW: Use `manual-slop_py_get_definition` on `cleanup`
- SAFETY: Note that cleanup() also clears other resources - document side effects
## Phase 2: Panel Implementation
- [ ] Task: Create cache panel
- WHERE: src/gui_2.py
- WHAT: Display cache stats
- HOW: imgui widgets
- SAFETY: Handle no cache
Focus: Create the GUI panel structure
## Phase 3: TTL & Controls
- [ ] Task: Display TTL countdown
- WHERE: src/gui_2.py
- WHAT: Time until cache rebuild
- HOW: Calculate from cache_created_at
- [ ] Task: Add clear button
- WHERE: src/gui_2.py
- WHAT: Manual cache clear
- HOW: Call ai_client.cleanup()
- [ ] Task 2.1: Add cache panel state variables
- WHERE: `src/gui_2.py` in `App.__init__` (around line 170)
- WHAT: Add minimal state if needed (likely none - read directly from ai_client)
- HOW: Follow existing state initialization pattern
- CODE STYLE: 1-space indentation
- SAFETY: No locks needed - read-only access to ai_client globals
## Phase 4: Verification
- [ ] Task: Test cache display
- [ ] Task: Conductor - Phase Verification
- [ ] Task 2.2: Create _render_cache_panel() method
- WHERE: `src/gui_2.py` after other `_render_*_panel()` methods
- WHAT: New method that displays cache statistics
- HOW:
```python
def _render_cache_panel(self) -> None:
if self.current_provider != "gemini":
return
if not imgui.collapsing_header("Cache Analytics"):
return
stats = ai_client.get_gemini_cache_stats()
# Render stats...
```
- CODE STYLE: 1-space indentation, NO COMMENTS
- [ ] Task 2.3: Integrate panel into main GUI
- WHERE: `src/gui_2.py` in `_gui_func()` method
- WHAT: Call `_render_cache_panel()` in appropriate location
- HOW: Add near token budget panel or in settings area
- SAFETY: Ensure not called during modal dialogs
## Phase 3: Statistics Display
Focus: Implement the visual statistics rendering
- [ ] Task 3.1: Implement cache status display
- WHERE: `src/gui_2.py` in `_render_cache_panel()`
- WHAT: Show cache existence and age
- HOW:
- `imgui.text(f"Cache Active: {stats['cache_exists']}")`
- `imgui.text(f"Age: {format_age(stats['cache_age_seconds'])}")`
- HELPER: Create `format_age(seconds: float) -> str` helper
- CODE STYLE: 1-space indentation
- [ ] Task 3.2: Implement TTL countdown display
- WHERE: `src/gui_2.py` in `_render_cache_panel()`
- WHAT: Show remaining TTL with percentage
- HOW:
- `remaining = stats['ttl_remaining']`
- `percentage = (remaining / stats['ttl_seconds']) * 100`
- Use `imgui.progress_bar()` for visual
- VISUAL: Warning color when percentage < 20% (use `vec4` colors defined at top of file)
- [ ] Task 3.3: Implement requests counter (optional enhancement)
- WHERE: `src/gui_2.py` in `_render_cache_panel()`
- WHAT: Show estimated "requests while cache active"
- HOW: Add `self._cache_request_count: int = 0` state, increment on send
- SAFETY: This requires hooking into send flow - may skip if complex
## Phase 4: Manual Controls
Focus: Implement the cache clear functionality
- [ ] Task 4.1: Add clear cache button
- WHERE: `src/gui_2.py` in `_render_cache_panel()`
- WHAT: Button that clears the Gemini cache
- HOW:
```python
if imgui.button("Clear Cache"):
ai_client.cleanup()
# Optionally set a flag to show "Cache cleared" message
```
- SAFETY: `cleanup()` clears ALL caches, not just Gemini - document this
- [ ] Task 4.2: Add clear confirmation/feedback
- WHERE: `src/gui_2.py` in `_render_cache_panel()`
- WHAT: Show feedback after clear
- HOW: Add `self._cache_just_cleared: bool = False` flag, show message, auto-clear after 3s
- CODE STYLE: 1-space indentation
## Phase 5: Testing
Focus: Verify all functionality works correctly
- [ ] Task 5.1: Write unit tests for cache panel
- WHERE: `tests/test_cache_panel.py` (new file)
- WHAT: Test panel visibility, stats display, clear button
- HOW: Use `mock_app` or `app_instance` fixture from `conftest.py`
- PATTERN: Follow `test_gui_phase4.py` as reference
- CODE STYLE: 1-space indentation
- [ ] Task 5.2: Write integration test with live_gui
- WHERE: `tests/test_cache_panel.py`
- WHAT: Test with actual Gemini provider (or mock)
- HOW: Use `live_gui` fixture, set provider to 'gemini', verify panel shows
- ARTIFACTS: Write to `tests/artifacts/`
- [ ] Task 5.3: Conductor - Phase Verification
- Run targeted tests: `uv run pytest tests/test_cache_panel.py -v`
- Verify no lint errors in modified files
- Manual visual verification in GUI
## Implementation Notes
### Thread Safety Analysis
- `ai_client.get_gemini_cache_stats()` reads `_gemini_cache` and `_gemini_cache_created_at`
- These are set on the asyncio worker thread during `_send_gemini()`
- Reading from GUI thread is safe (atomic types) but values may be slightly stale
- No locks required for display purposes
### Code Style Checklist
- [ ] 1-space indentation throughout
- [ ] CRLF line endings on Windows
- [ ] No comments unless explicitly documenting complex logic
- [ ] Type hints on all new functions
- [ ] Follow existing `vec4` color naming pattern
### Files Modified
- `src/gui_2.py`: Add `_render_cache_panel()`, integrate into `_gui_func()`
- `tests/test_cache_panel.py`: New test file
### Dependencies
- Existing: `src/ai_client.py::get_gemini_cache_stats()`
- Existing: `src/ai_client.py::cleanup()`
- Existing: `imgui_bundle::imgui`

View File

@@ -1,21 +1,118 @@
# 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 not displayed in GUI.
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
- **Non-Blocking**: Cache queries MUST NOT block UI.
- **Efficient Polling**: Cache stats SHOULD be polled, not pushed.
### 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
- **Cache Status**: Display active cache count and size.
- **Hit/Miss Ratio**: Calculate and display cache efficiency.
- **TTL Countdown**: Show time until next cache rebuild.
- **Manual Clear**: Button to manually clear cache.
### 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.
- [ ] Hit/miss ratio calculated correctly.
- [ ] TTL countdown visible.
- [ ] Manual clear button works.
- [ ] Uses existing get_gemini_cache_stats().
- [ ] 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