- Add dual-stream calibration: phone sends both raw and cropped preview
frames during calibration so users can see what practice will look like
- Add "Adjust" button to modify existing manual calibration without
resetting to auto-detection first
- Hide calibration quad editor overlay when not in calibration mode
- Fix rotation buttons to update cropped preview immediately
- Add rate limiting (10fps) for cropped preview frames during calibration
- Fix multiple bugs preventing dual-stream mode from working:
- Don't mark calibration as complete during preview mode
- Don't stop detection loop when receiving preview calibration
- Sync refs properly in frame mode change effects
Also includes accumulated formatting and cleanup changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply code formatting across codebase
- Add new vision training boundary frames
- Update model configurations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major refactoring of worksheet parsing to use centralized state management:
New architecture:
- WorksheetParsingContext: React context provider for parsing state
- state-machine.ts: Typed reducer with actions for streaming lifecycle
- sse-parser.ts: Shared SSE parsing utility for OpenAI Responses API
- usePartialJsonParser.ts: Progressive JSON extraction during streaming
Streaming UI improvements:
- ParsingProgressOverlay: Dark overlay on photo tile during parsing
- ParsingProgressPanel: Collapsible reasoning text panel
- ProgressiveHighlightOverlay: Problem boxes light up as LLM parses
- New streaming API routes: /parse/stream and /parse-selected/stream
Bug fixes during testing:
- Fix TypeScript error: cast event.response for id access in sse-parser
- Fix reparse reasoning display: preserve "processing" status for reparse
- Fix concurrent parsing: revert previous attachment status when switching
- Fix problem count: track dispatched problems to prevent duplicates
Components updated to use context:
- SummaryClient: Wrapped with WorksheetParsingProvider
- OfflineWorkSection: Uses context instead of local streaming state
- PhotoViewerEditor: Uses context for coordinated parsing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cancel button to gallery thumbnails when parsing in progress
- Add cancel button to fullscreen PhotoViewerEditor when parsing
- Add cancel button for re-parsing in progress (fullscreen view)
- Track reparsingPhotoId to show correct status per-photo in both views
- Gallery shows "Re-parsing..." badge on specific photo being re-parsed
- DELETE endpoint resets parsing status for immediate retry
Also includes codebase-wide formatting from biome.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove per-problem Exclude/Restore buttons from EditableProblemRow
- Add bulk "Exclude Selected" and "Restore Selected" buttons to selection toolbar
- Add toast notifications for approve success/failure
- Close viewer and refresh page after successful approve to show updated session
- Fix mutation to properly await res.json() before returning
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixed two critical bugs preventing ten-frames from rendering:
1. **Mastery mode not handled** (typstGenerator.ts:61)
- Code only checked for 'smart' | 'manual' modes
- Mastery mode fell into manual path, tried to use boolean flags that don't exist
- Resulted in all display options being `undefined`
- Fix: Check for both 'smart' OR 'mastery' modes (both use displayRules)
2. **Typst array membership syntax** (already fixed in previous commit)
- Used `(i in array)` which doesn't work in Typst
- Changed to `array.contains(i)`
Added comprehensive unit tests (tenFrames.test.ts):
- Problem analysis tests (regrouping detection)
- Display rule evaluation tests
- Full Typst template generation tests
- Mastery mode specific tests
- All 14 tests now passing
Added debug logging to trace display rules resolution:
- displayRules.ts: Shows rule evaluation per problem
- typstGenerator.ts: Shows enriched problems and Typst data
- Helps diagnose future issues
The issue was that mastery mode (which uses displayRules like smart mode)
was being treated as manual mode (which uses boolean flags), resulting in
undefined display options.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Recover all changes from stash including:
- Linter/formatter updates across codebase
- Settings permission updates for git checkout
This commit captures the complete state of work that was
stashed during the previous session's git operations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove all scaffolding (carry boxes, answer boxes, place value colors) from ten-frame examples
- Show only the core addition problems with ten-frame visualization
- Add transparent background support for blog examples
- Implement smart color replacement for dark theme visibility:
- White operator symbols (+) and horizontal bars (visible on dark background)
- Black digits on white cells (preserved contrast)
- White structural borders and lines
- Update generateTenFrameExamples.ts with post-processing to handle SVG colors
- Regenerate all 4 ten-frame example SVGs with clean, minimal presentation
The examples now focus purely on demonstrating the ten-frame concept
without distracting extra scaffolding elements.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes production error "Cannot read properties of undefined (reading 'carryBoxes')"
that occurred when users tried to adjust difficulty settings.
Root cause: displayRules was undefined for new users or users with old V1 config
in database. Difficulty adjustment buttons accessed displayRules.carryBoxes without
checking if displayRules existed first.
Changes:
- AdditionWorksheetClient: Initialize displayRules with defaults when missing
- ConfigPanel: Use null-coalescing operators instead of non-null assertions
- ConfigPanel: Add error logging when required fields are missing
- NEW: WorksheetErrorBoundary component to catch all errors in worksheet page
- page.tsx: Wrap client component with error boundary
This ensures users see helpful error messages instead of blank pages,
and never need to open the browser console to understand what went wrong.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>