Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ poetry.lock

# Game state persistence file
game_state.json
coverage.xml

163 changes: 138 additions & 25 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,39 +374,152 @@ if 'key' in app.storage.general:
- Responsive design classes
- Clear visual feedback

## MCP Tools Used
## MCP Tools & Memory Management

### 🛑 STOP! SAVE TO MEMORY NOW - NOT LATER!

#### THROUGHOUT EVERY SESSION:
- ✅ Just solved something? → SAVE NOW
- ✅ Created a script? → SAVE NOW
- ✅ Fixed an error? → SAVE NOW
- ✅ Made a decision? → SAVE NOW
- ✅ Discovered a pattern? → SAVE NOW

**DON'T WAIT UNTIL THE END OF THE SESSION!**

### Memory-First Protocol (CRITICAL)
- **ALWAYS** search memory BEFORE starting any work: `mcp__mcp-memory__searchMCPMemory "bingo [topic]"`
- **ALWAYS** save solutions after fixing issues: `mcp__mcp-memory__addToMCPMemory "bingo: Problem: X, Solution: Y"`
- **Save context switches**: When interrupted or switching tasks, save current state
- **Capture train of thought**: Document reasoning and decision paths

### Memory Save Triggers (DO IMMEDIATELY)
- After creating any script → Save its purpose and usage
- After fixing any error → Save problem + solution
- After file reorganization → Save what moved where
- After discovering pattern → Save the insight
- After making decision → Save the rationale
- After solving problem → Save approach + result

### Session Start Protocol for Bingo
```bash
# 1. Restore context from last session
mcp__mcp-memory__searchMCPMemory "bingo last session state"
mcp__mcp-memory__searchMCPMemory "bingo open tasks TODO"
mcp__mcp-memory__searchMCPMemory "Jonathan workflow guidelines best practices"

# 2. Rebuild mental model
tree . -I 'node_modules' -L 2
cat CLAUDE.md

# 3. Load comprehensive project memory
mcp__mcp-memory__searchMCPMemory "bingo current state"
mcp__mcp-memory__searchMCPMemory "bingo where I left off"
mcp__mcp-memory__searchMCPMemory "bingo blockers questions"
mcp__mcp-memory__searchMCPMemory "bingo solutions patterns"
mcp__mcp-memory__searchMCPMemory "bingo nicegui patterns"
mcp__mcp-memory__searchMCPMemory "bingo state persistence"
mcp__mcp-memory__searchMCPMemory "bingo testing infrastructure"

# 4. Check work state
git status
git diff
git log --oneline -10
gh pr list --assignee @me --state open
```

### MCP Tools Available

### For This Project
When working on the Bingo project, the following MCP tools are particularly useful:
1. **mcp-memory** (Always Active - External Brain)
- `mcp__mcp-memory__searchMCPMemory "[query]"` - Search stored knowledge
- `mcp__mcp-memory__addToMCPMemory "content"` - Save new knowledge
- Always prefix with "bingo:" for project isolation

1. **mcp-memory** (Long-term memory)
- `mcp__mcp-memory__searchMCPMemory`: Search for past solutions and patterns
- `mcp__mcp-memory__addToMCPMemory`: Save solutions and learnings
- Always prefix entries with "bingo:" for project isolation
2. **sequentialthinking** - For complex reasoning (especially with Sonnet 4)
- Use for architectural decisions and complex debugging
- Saves reasoning process to memory automatically

2. **context7** (Documentation lookup)
3. **context7** (Documentation lookup)
- `mcp__context7__resolve-library-id`: Find library IDs (e.g., NiceGUI)
- `mcp__context7__get-library-docs`: Get library documentation
- Used to research NiceGUI storage patterns

3. **sequentialthinking** (Complex reasoning)
- `mcp__sequentialthinking__sequentialthinking`: Break down complex problems
- Useful for architectural decisions and debugging

4. **serena** (Code intelligence)
- Activate with: `mcp__serena__activate_project`
- Activate with: `mcp__serena__activate_project "bingo"`
- Provides symbol search, refactoring, and code analysis
- Manages project-specific memories

### Example Usage
```python
# Search for past solutions
mcp__mcp-memory__searchMCPMemory("bingo state persistence")
### Memory Templates for Bingo Project

# Save new solution
mcp__mcp-memory__addToMCPMemory("bingo: Fixed state persistence using StateManager pattern...")
#### Error Solutions
```
Project: bingo
Error: [exact error message]
Context: [NiceGUI version, test environment, etc.]
Solution: [step-by-step fix]
Code Before: [relevant code showing issue]
Code After: [corrected code]
Validation: [how verified it worked]
Tags: bingo, error-fix, [component], [technology]
```

#### Testing Infrastructure
```
Project: bingo
Component: [StateManager/UI/Testing]
Issue: [what needed testing/fixing]
Approach: [testing strategy used]
Implementation: [specific test code/patterns]
Results: [coverage/performance metrics]
Patterns: [reusable testing patterns discovered]
Tags: bingo, testing, [unit/integration/e2e], [component]
```

#### NiceGUI Specific Patterns
```
Project: bingo
NiceGUI Pattern: [state management/UI/timers/etc.]
Problem: [what was challenging]
Solution: [NiceGUI-specific approach]
Code Example: [working implementation]
Gotchas: [things to watch out for]
Performance: [any performance considerations]
Tags: bingo, nicegui, [pattern-type], [version]
```

#### StateManager Architecture
```
Project: bingo
Architecture Decision: [what was decided]
Previous Approach: [old way - app.storage.general]
New Approach: [StateManager pattern]
Implementation: [key code/patterns]
Benefits: [persistence, thread-safety, etc.]
Testing Strategy: [how we verified it works]
Tags: bingo, architecture, state-persistence, statemanager
```

### Common Search Patterns for Bingo
```bash
# Starting work
mcp__mcp-memory__searchMCPMemory "bingo session startup protocol"
mcp__mcp-memory__searchMCPMemory "bingo current priorities"

# Debugging
mcp__mcp-memory__searchMCPMemory "bingo [error-type] solutions"
mcp__mcp-memory__searchMCPMemory "bingo nicegui [issue-type]"
mcp__mcp-memory__searchMCPMemory "bingo testing [test-type] patterns"

# Development
mcp__mcp-memory__searchMCPMemory "bingo statemanager patterns"
mcp__mcp-memory__searchMCPMemory "bingo ci optimization"
mcp__mcp-memory__searchMCPMemory "bingo deployment troubleshooting"
```

# Get NiceGUI docs
mcp__context7__resolve-library-id("nicegui")
mcp__context7__get-library-docs("/zauberzeug/nicegui", "storage persistence")
```
### What to Save for Bingo (SAVE IMMEDIATELY)
- **Every StateManager fix/enhancement** with before/after code
- **NiceGUI UI patterns** that work well for this app
- **Testing strategies** that prove effective (unit/integration/e2e)
- **CI/CD optimizations** and performance improvements
- **Docker/Helm deployment issues** and their solutions
- **Performance bottlenecks** and optimization approaches
- **User experience improvements** and their impact
- **Architecture decisions** with reasoning and alternatives considered
134 changes: 67 additions & 67 deletions tests/test_hot_reload_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,73 +21,73 @@ class TestHotReloadIntegration:

@pytest.mark.asyncio
async def test_state_persists_on_page_reload(self):
"""Test that game state persists when page is reloaded."""
async with async_playwright() as p:
# Launch browser
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()

try:
# Navigate to the app
await page.goto("http://localhost:8080")
await page.wait_for_load_state("networkidle")

# Get initial board state - count clickable tile divs
initial_tiles = await page.locator("[style*='cursor: pointer']").count()
assert initial_tiles >= 25, f"Should have at least 25 tiles, got {initial_tiles}"

# Get the actual tile texts from the page to click the first few
# Since tiles might have text split across multiple elements,
# we'll click by index position instead
tile_elements = await page.locator("[style*='cursor: pointer']").all()

# Click tiles at specific indices (avoiding the center FREE MEAT tile at index 12)
tiles_to_click_indices = [0, 1, 5] # Top-left, second in first row, first in second row

for index in tiles_to_click_indices:
await tile_elements[index].click()
await asyncio.sleep(0.2) # Wait for state save

# Take screenshot before reload
await page.screenshot(path="before_reload.png")

# Check state file exists and has correct data
state_file = Path("game_state.json")
assert state_file.exists(), "State file should exist"

with open(state_file, 'r') as f:
state = json.load(f)

# Verify clicked tiles are saved (including FREE MEAT)
assert len(state['clicked_tiles']) >= 4, f"Should have at least 4 clicked tiles, got {len(state['clicked_tiles'])}"

# Store clicked positions for verification
clicked_positions = set(tuple(pos) for pos in state['clicked_tiles'])

# Reload the page
await page.reload()
await page.wait_for_load_state("networkidle")

# Take screenshot after reload
await page.screenshot(path="after_reload.png")

# Verify the board is restored
restored_tiles = await page.locator("[style*='cursor: pointer']").count()
assert restored_tiles >= 25, f"Should still have at least 25 tiles after reload, got {restored_tiles}"

# Read state file again to verify it still has the same data
with open(state_file, 'r') as f:
restored_state = json.load(f)

restored_positions = set(tuple(pos) for pos in restored_state['clicked_tiles'])
assert clicked_positions == restored_positions, "Clicked tiles should be preserved"

# Verify we have the expected number of tiles clicked
# Should be 3 tiles we clicked + 1 FREE MEAT tile = 4 total
assert len(restored_positions) == 4, f"Should have exactly 4 clicked tiles after reload, got {len(restored_positions)}"

finally:
await browser.close()
"""Test that game state persists when page is reloaded."""
async with async_playwright() as p:
# Launch browser
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
try:
# Navigate to the app
await page.goto("http://localhost:8080")
await page.wait_for_load_state("networkidle")
# Get all clickable tiles
tiles = await page.locator("[style*='cursor: pointer']").all()
assert len(tiles) == 25, f"Should have exactly 25 tiles, got {len(tiles)}"
# Click tiles by position (avoiding FREE MEAT at position 12)
# Map positions to board coordinates for verification
tiles_to_click = [
0, # (0,0) - top-left
4, # (0,4) - top-right
6, # (1,1) - second row, second col
]
for tile_index in tiles_to_click:
await tiles[tile_index].click()
await asyncio.sleep(0.2) # Wait for state save
# Take screenshot before reload
await page.screenshot(path="before_reload.png")
# Check state file exists and has correct data
state_file = Path("game_state.json")
assert state_file.exists(), "State file should exist"
with open(state_file, 'r') as f:
state = json.load(f)
# Verify clicked tiles are saved (our 3 clicks + FREE MEAT)
assert len(state['clicked_tiles']) == 4, f"Should have 4 clicked tiles, got {len(state['clicked_tiles'])}"
# Store clicked positions for verification
clicked_positions = set(tuple(pos) for pos in state['clicked_tiles'])
# Reload the page
await page.reload()
await page.wait_for_load_state("networkidle")
# Take screenshot after reload
await page.screenshot(path="after_reload.png")
# Verify the board is restored
restored_tiles = await page.locator("[style*='cursor: pointer']").all()
assert len(restored_tiles) == 25, f"Should still have 25 tiles after reload, got {len(restored_tiles)}"
# Read state file again to verify it still has the same data
with open(state_file, 'r') as f:
restored_state = json.load(f)
restored_positions = set(tuple(pos) for pos in restored_state['clicked_tiles'])
assert clicked_positions == restored_positions, "Clicked tiles should be preserved"
# Verify we have the expected number of tiles clicked
assert len(restored_positions) == 4, f"Should have exactly 4 clicked tiles after reload, got {len(restored_positions)}"
finally:
await browser.close()


@pytest.mark.asyncio
async def test_state_persists_across_sessions(self):
Expand Down