# Next Session Prompt - Phase 40.3.3: Digit Entry ## Context Setup Hi! We're continuing the vim-sudoku unified API implementation. I need you to: 1. **Read these files first** (in order): - `IMPLEMENTATION_PLAN.md` - Overall roadmap - `IMPLEMENTATION.md` - Full implementation log (read ALL iterations) - `AGENTS.md` in the root (../../AGENTS.md) - Code conventions - `UNIFIED_API.md` in the root - Architecture reference 2. **Review current state**: - We're in Phase 40.3.3 (digit entry for edit mode) - Check latest git commits to see what's been done - Current working directory: `/home/pastilhas/projects/vimazing/games/vim-sudoku` ## What We've Completed ### Phase 40.1: Basic Cursor (✅ DONE) - hjkl movement with bounds checking - Blue cursor highlight - Red flash on invalid moves - All working perfectly ### Phase 40.2: Complete Vim Motions (✅ DONE) - Anchor moves: 0, ^, $, gg, G - Count prefixes: 5j, 10l, etc. - Repeat motion: . - **The 0 caveat solved**: `if (key === '0' && countRef.current === '')` → anchor, else count - gg requires two presses (pendingGRef state) - All tested and flawless ### Phase 40.3: Edit Mode State Machine (✅ DONE) **Phase 40.3.1:** Mode state (normal/edit) - `i` to enter edit mode - `Escape` to exit edit mode - Visual feedback using existing CSS classes **Phase 40.3.2:** Edit mode rules - Given cells (`.given` class) → Red flash, edit blocked - Empty cells → Edit allowed - User-entered cells (`.user-entered` class) → Edit allowed - Vim motions blocked in edit mode **Visual Indicators:** - Normal mode: `.active` class (blue glow) - Edit mode: `.editing` class (yellow/amber pulsing glow) - Invalid: `.invalid-move` class (red flash 500ms) ## Current Architecture ### Key Files ``` src/ ├── types.ts # Main type exports ├── useGame.ts # Orchestrator ├── useBoard/ │ ├── types.ts # BoardManager │ ├── useBoard.ts # Board management │ ├── SudokuGenerator.ts # Puzzle generation (class) │ └── SudokuRenderer.ts # DOM rendering (class) ├── useCursor/ │ ├── types.ts # CursorManager, CursorMode, Motion │ ├── useCursor.ts # Cursor + mode state │ ├── useCursorRender.ts # Visual feedback │ └── useVimMotions.ts # Vim motion processor ├── useGameStatus/ │ ├── types.ts # GameStatus, GameStatusManager │ └── useGameStatus.ts # Game lifecycle └── useScore/ ├── types.ts # ScoreManager (mocked for now) └── useScore.ts # Scoring (mocked for now) ``` ### Current State - Board: 9x9 grid, puzzle generation working - Cursor: Full vim motions + edit mode state machine - Mode: 'normal' | 'edit' with proper validation - Visual: All feedback working (blue/yellow/red) ## Phase 40.3.3: Digit Entry (NEXT TASK) ### Goal Allow user to type digits 1-9 when in edit mode to fill cells. ### Requirements **When in Edit Mode:** 1. User can type digits 1-9 2. Digit gets written to the current cell 3. Board state updates (needs board integration) 4. Cell shows digit with `.user-entered` class 5. Stay in edit mode after entering digit (don't auto-exit) 6. Pressing Escape exits edit mode **When in Normal Mode:** 7. Digits 0-9 are count prefixes (already working) 8. No digit entry allowed ### Implementation Strategy **Step 1: Board State Management** - `useBoard` needs to track current board state (not just initial) - Add `boardRef` with current puzzle state - Add method: `setCell(row, col, value)` to update board - Re-render board after cell update **Step 2: Update useCursor** - In edit mode, detect digit keys (1-9) - Call board's `setCell()` to update state - Trigger board re-render - Stay in edit mode (don't exit) **Step 3: Integration** - Pass board methods to useCursor - Ensure re-render updates cell classes correctly - User-entered cells get `.user-entered` class ### Key Considerations **Board Representation:** - Board stored as 81-char string in `boardRef.current` - '.' for empty, '1'-'9' for filled - `initialBoardRef` keeps original puzzle (immutable) - `solutionRef` keeps solution (for validation later) **Cell Updates:** ```typescript // In useBoard function setCell(row: number, col: number, value: string): void { const board = boardRef.current.split(''); const index = row * 9 + col; board[index] = value; boardRef.current = board.join(''); renderBoard(); // Re-render to show change } ``` **Passing to useCursor:** ```typescript // In useGame const cursor = useCursor(gameStatusManager, containerRef, board.setCell); ``` ### Testing Checklist - [ ] Press i on empty cell → edit mode - [ ] Type '5' → Cell shows 5 - [ ] Cell has `.user-entered` class - [ ] Escape → normal mode - [ ] Navigate to another cell → first cell still shows 5 - [ ] Press i on given cell → red flash (no edit) - [ ] In normal mode, type '5j' → moves down 5 (count works) ## Important Notes ### Agent Rules (from AGENTS.md) - **No `useCallback` or `useMemo`** (React 19 compiler handles it) - **No comments** unless explicitly requested - **Type-first approach**: Define types before implementation - **Follow existing patterns**: Look at vim-maze and current code - **Update IMPLEMENTATION.md**: After completing the phase ### Code Conventions - Plain functions, not wrapped in hooks - Explicit `import type` for types - Refs for non-reactive state, useState for reactive - Clean, minimal whitespace - Descriptive names (no `data`, `item`, etc.) ### Git Workflow - Small, focused commits - Clear commit messages (what, why) - Update IMPLEMENTATION.md with each phase - Test builds before committing ## How to Start 1. Read the files I mentioned at the top 2. Review latest git commits: `git log --oneline -10` 3. Confirm understanding of current state 4. Ask me if anything is unclear 5. Start implementing Phase 40.3.3 step by step Let's implement digit entry slowly and carefully, testing at each step! --- ## Quick Reference **Current Mode State:** In `useCursor.ts` ```typescript const [mode, setMode] = useState('normal'); ``` **Edit Mode Check:** In keyboard handler ```typescript if (mode === 'edit') { if (key === 'Escape') setMode('normal'); // Add digit handling here (1-9) return; } ``` **Board String Format:** ``` "52...8.4....7...4......6.....8.....3.9....8..1...2.......2....6...3....7..8...9." // 81 characters: digits for givens, '.' for empty ``` Ready to continue! 🚀