Commit Graph

70 Commits

Author SHA1 Message Date
Thomas Hallock 3c9406afc5 fix(practice): improve mobile layout + floating abacus positioning
- Add bottomOffset/rightOffset to MyAbacusContext for virtual keyboard avoidance
- NumericKeypad sets offsets when mounted (48px bottom, 100px right)
- Floating abacus repositions above/beside keyboard in portrait/landscape
- PracticeSubNav: fix horizontal overflow with minWidth: 0 on flex children
- SessionProgressIndicator: allow proper flex shrinking
- ActiveSession: reduce padding/gaps, use flex layout to fill available space
- PracticeClient: use fixed positioning with proper insets for all orientations
  - Portrait: bottom 48px for keypad
  - Landscape: right 100px for keypad
  - Desktop: no offsets needed
- Prevent viewport scrolling during practice sessions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 19:49:59 -06:00
Thomas Hallock 4daf7b7433 feat(practice): add SkillUnlockBanner + session summary improvements
This commit includes accumulated work from the SessionMode system:

- Add SkillUnlockBanner component for celebrating skill mastery
- Improve SessionSummary to show skill unlock celebrations
- Add session detail page at /practice/[studentId]/session/[sessionId]
- Update seedTestStudents script with more realistic test data
- Extend skill-tutorial-config with more skill mappings
- Improve BKT compute with better uncertainty handling
- Update progress-manager with skill completion tracking
- Remove legacy sessions API routes (replaced by session-plans)
- Add migration 0037 for practice_sessions schema cleanup
- Add plan documents for celebration wind-down and SessionMode
- Update gitignore to exclude db backups

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 15:16:34 -06:00
Thomas Hallock b94f5338e5 feat(skills-modal): add spring animations and UX improvements
- Add smooth spring-animated accordion expand/collapse using react-spring
- Add dynamic scroll indicators that show when content is scrolled
- Auto-scroll to show expanded category content optimally
- Replace ambiguous arrows with "Show/Hide" + rotating chevron
- Make modal full-screen on mobile, centered on desktop
- Add sticky category headers within scroll container
- Fix z-index layering using shared constants
- Add optimistic updates for skill mutations (instant UI feedback)
- Fix React Query cache sync for live skill updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 07:23:14 -06:00
Thomas Hallock 6a4dd694a2 feat(blog): add interactive ECharts for BKT validation blog post
- Add ValidationCharts with tabbed interface for A/B trajectory data
  - "All Skills" tab: shows 6 skills at once, toggle Adaptive/Classic
  - "Single Skill" tab: interactive skill selector for individual comparison
  - "Convergence" tab: bar chart comparing sessions to 80% mastery
  - "Data Table" tab: summary with advantage calculations
- Add SkillDifficultyCharts for skill difficulty model visualization
- Create snapshot-based test infrastructure for trajectory data
  - skill-difficulty.test.ts generates A/B mastery trajectories
  - Snapshots capture session-by-session mastery for 6 deficient skills
- Add generator scripts to convert snapshots to JSON for blog charts
  - generateMasteryTrajectoryData.ts → ab-mastery-trajectories.json
  - generateSkillDifficultyData.ts → skill-difficulty-report.json
- Add skill-specific difficulty multipliers to SimulatedStudent
  - Basic skills: 0.8-0.9x (easier)
  - Five-complements: 1.2-1.3x (moderate)
  - Ten-complements: 1.6-2.0x (harder)
- Document SimulatedStudent model in SIMULATED_STUDENT_MODEL.md

Results show adaptive mode reaches 80% mastery faster for all 6 tested
skills (4-0 at 50% threshold, 6-0 at 80% threshold).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 13:16:47 -06:00
Thomas Hallock a3e79dac74 chore: sync lockfile with package.json
Regenerate pnpm-lock.yaml to fix CI deployment failure.
The lockfile was out of sync causing "ERR_PNPM_OUTDATED_LOCKFILE"
in GitHub Actions when running with frozen-lockfile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 07:06:29 -06:00
Thomas Hallock e937c05323 chore: miscellaneous updates and documentation
- Update know-your-world implementation docs
- Update decomposition CSS styles
- Update AbacusReact component
- Update gallery template
- Update dependencies (pnpm-lock.yaml)
- Update biome config

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 11:40:59 -06:00
Thomas Hallock 1e6153ee8b feat(know-your-world): add fire tracer animation for learning mode takeover
Add animated fire/sparkle tracer effect around region outlines in learning mode:
- Tracer follows simplified path (using simplify-js) for smooth coastlines
- Supports multiple islands with simultaneous animations
- Progressive intensity as letters are typed:
  - Speed increases exponentially (15s → 0.075s, 200x faster)
  - Opacity fades in (25% → 100%)
  - Sparkle count grows exponentially (1 → 48)
- 750ms laser effect delay after final letter before dismissing
- Uses react-spring for smooth transitions
- Performance optimized: removed filters from particles

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 09:44:03 -06:00
Thomas Hallock 5318d0dd89 feat(know-your-world): add mobile virtual keyboard and space-skipping
- Add SimpleLetterKeyboard component for touch devices (react-simple-keyboard)
- Skip spaces when counting letters for name confirmation
  (e.g., "US Virgin Islands" → type U, S, V)
- Hide MyAbacus floating button when virtual keyboard is shown
- Add Storybook stories for testing letter confirmation flow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 13:08:39 -06:00
Thomas Hallock 3f4691e8a3 feat(know-your-world): live crop updates and safe zone improvements
- Add runtime crop override system for live DevCropTool updates without page reload
- Fix SVG letterboxing in DevCropTool coordinate conversion (screenToSvg/svgToScreen)
- Hide all UI (nav, GameInfoPanel) during crop mode for unobstructed drawing
- Show debug overlay (leftover/crop rectangles) even when no custom crop defined
- Use full map bounds as implicit crop when no custom crop exists
- Ensure map always fits within leftover area (not under UI elements)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:46:23 -06:00
Thomas Hallock 743adae92d refactor: use flatten-js for precise geometric intersection detection
Replace point sampling with proper computational geometry using @flatten-js/core.

Previous approach (strategic points):
- Tested 9 hardcoded points (corners + center + edge midpoints)
- Still sampling-based, just smarter sampling
- Could miss edge cases with complex shapes

New approach (flatten-js):
- Convert SVG path to Polygon using getPointAtLength() (50 samples)
- Convert detection box to Box in SVG coordinates
- Use polygon.intersect(box) for precise intersection test
- Also checks boxContainsRegion for tiny regions fully inside box
- Proper computational geometry, not heuristics

Algorithm:
1. Sample 50 points evenly along SVG path using getTotalLength()
2. Create Polygon from sampled points
3. Transform detection box corners to SVG coordinates
4. Create Box from transformed corners
5. Check: polygon.intersect(box) || box.contains(polygon.box)

Benefits:
- Mathematically correct intersection detection
- No guessing about where to sample
- Handles all cases: intersecting, contained, disjoint
- Fallback to 9-point sampling if flatten-js fails

Dependencies:
- Added @flatten-js/core for 2D computational geometry

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 07:05:57 -06:00
Thomas Hallock 05fc5cfe49 fix: regenerate lockfile to remove big.js dependencies 2025-11-19 19:31:59 -06:00
Thomas Hallock 68cef7c0d0 chore: update lockfile after big.js revert 2025-11-19 19:26:02 -06:00
Thomas Hallock 3bf127f344 feat: add precision controls for tiny regions in Know Your World
Implement automatic cursor dampening, super zoom on hover, and quick-escape to make sub-pixel regions (Gibraltar 0.08px, Jersey 0.82px) clickable. Fix crosshair accuracy to match dampened cursor position, add excluded region visualization (gray pre-labeled), and increase unfound region contrast (0.3→0.7 opacity).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 18:06:34 -06:00
Thomas Hallock 25e24a7cbc feat: add Know Your World geography quiz game
Add new arcade game for testing geography knowledge:

Game Features:
- 4 phases: Setup, Study, Playing, Results
- 3 multiplayer modes: Cooperative, Race, Turn-Based
- 2 maps: World countries, USA states
- Configurable study mode (0, 30, 60, or 120 seconds)
- Return to Setup and New Game options in game menu
- Small region labels with arrows for improved visibility

Map Rendering:
- 8-color deterministic palette with hash-based assignment
- Opacity-based states (20-27% unfound, 100% found)
- Enhanced label visibility with text shadows
- Smart bounding box calculation for small regions
- Supports both easy (outlines always visible) and hard (outlines on hover/found) difficulty

Game Modes:
- Cooperative: All players work together to find all regions
- Race: First to click gets the point
- Turn-Based: Players take turns finding regions

Study Phase:
- Optional timed study period before quiz starts
- Shows all region labels for memorization
- Countdown timer with skip option

Dependencies:
- Add @svg-maps/world and @svg-maps/usa packages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 20:04:52 -06:00
Thomas Hallock de270767c0 chore: regenerate pnpm-lock.yaml
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 11:34:17 -06:00
Thomas Hallock e708add9f2 fix: respect user's layout options (problemNumbers/cellBorders) in mastery mode
The problem: When in mastery mode, layout toggles (Problem Numbers and
Cell Borders) appeared to work but had no effect on the worksheet preview.

Root cause: Mastery mode was using hardcoded recommendedScaffolding from
skill definitions, completely overriding user's displayRules choices.

Solution: Merge user's displayRules with skill's recommended scaffolding,
giving user's layout choices (problemNumbers, cellBorders) priority while
still respecting the skill's pedagogical scaffolding recommendations for
other display options.

Changes:
- validation.ts: Override layout options with user choices in mastery mode
- Remove debug logging from OrientationPanel, AdditionWorksheetClient,
  preview API route, and typstGenerator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 18:53:57 -06:00
Thomas Hallock 2d33f35c4d fix: correct GPT-5 API parameters and surface actual grading errors
Two critical fixes for worksheet grading:

1. **Fix OpenAI Responses API parameters**
   - Move `verbosity` from top-level to `text.verbosity`
   - API was rejecting requests with 400 error
   - Confirmed against GPT-5 Responses API documentation

2. **Surface actual grading errors in UI**
   - Add `error_message` column to worksheet_attempts table
   - Store actual API/grading errors in database
   - Display real error messages instead of generic "too blurry" text
   - Users now see OpenAI API errors, validation failures, etc.

Changes:
- Updated gradeWorksheet.ts API call structure
- Created migration 0020 for error_message column
- Updated processAttempt.ts to save error messages
- Updated API route to return errorMessage field
- Updated results page to display actual errors

Now when grading fails, users see helpful error messages like:
"Unsupported parameter: 'verbosity'..." instead of just "too blurry"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 06:12:10 -06:00
Thomas Hallock cd75df7221 chore: restore stashed work from previous session
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>
2025-11-08 14:59:40 -06:00
Thomas Hallock ceefb2f1bd fix: add missing blog dependencies to package.json
Add gray-matter, remark, remark-gfm, and remark-html dependencies
that were missing from the blog feature commits, causing webpack
"Module not found" errors in CI/CD.

These packages are required by src/lib/blog.ts for markdown processing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 12:19:00 -06:00
Thomas Hallock e0585b8ac7 chore: update pnpm lockfile for openscad-wasm-prebuilt
Add lockfile entries for openscad-wasm-prebuilt package.

This complements commit af9c1add which added the dependency to package.json.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:45:02 -06:00
Thomas Hallock dafdfdd233 feat: add 3D printing support for abacus models
Add comprehensive 3D printing capabilities for generating custom
abacus models in STL format:

- OpenSCAD integration in Docker container
- API endpoint: POST /api/abacus/generate-stl
- Background job processing with status monitoring
- STL file preview with Three.js
- Interactive abacus customization page at /create/abacus
- Configurable parameters: columns, bead shapes, dimensions, colors
- Export formats: STL (for 3D printing), SCAD (for editing)

Components:
- STLPreview: Real-time 3D model viewer
- JobMonitor: Background job status tracking
- AbacusCustomizer: Interactive configuration UI

Docker: Add OpenSCAD and necessary 3D printing tools
Dependencies: Add three, @react-three/fiber, @react-three/drei

Generated models stored in public/3d-models/
Documentation: 3D_PRINTING_DOCKER.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 10:53:54 -06:00
Thomas Hallock 946e5d1910 feat: install embla-carousel-autoplay for games carousel
Add embla-carousel-autoplay dependency to enable smooth automatic
rotation of games in the hero carousel.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 10:53:54 -06:00
Thomas Hallock 642ae95738 feat: install embla-carousel-react for player profile carousel
Add embla-carousel-react dependency to enable smooth carousel
functionality for displaying player profiles on the games page.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 07:04:09 -06:00
Thomas Hallock 37cea1c199 chore: update pnpm lockfile for react-textfit types
Update pnpm-lock.yaml to include the newly added @types/react-textfit
package dependency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 13:46:10 -06:00
Thomas Hallock 9fd54067ce feat(rithmomachia): auto-size tab labels with react-textfit
Replace ellipsized tab labels with react-textfit library:
- Install react-textfit package
- Use Textfit component for tab text labels
- Auto-scales font size (8px-14px) using binary search to fit width
- No more ellipsis (...) on narrow tabs
- Full tab labels always visible and readable
- Icon stays fixed size, only text scales

Tab labels now automatically shrink to fit available space while
remaining fully readable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 12:23:24 -06:00
Thomas Hallock f457f1a1c2 feat(rithmomachia): add guide docking with resizable panels
Implement ability to dock the Rithmomachia playing guide to left or right
side of the board screen. When docked, guide and board are in separate
panels with a resizable divider between them.

Features:
- Drag guide to left/right edge (within 100px) to dock it
- Resizable divider using react-resizable-panels library
- Guide defaults to 35% width, resizable between 20-50%
- Board takes remaining space (minimum 50%)
- Undock button (⛶) returns guide to floating modal mode
- No overlap between board and guide when docked
- Dragging disabled when docked
- Styling adjusted for docked mode (no shadows, no border-radius)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 10:17:26 -06:00
Thomas Hallock 9016b76024 feat(i18n): migrate from react-i18next to next-intl
- Install next-intl package
- Configure next-intl middleware for cookie-based locale detection
- Set up routing config with supported locales (en, de, ja, hi, es, la)
- Create request config for server-side locale resolution
- Migrate Rithmomachia guide sections to next-intl
- Update translation calls to use next-intl's useTranslations hook
- Remove old react-i18next config

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 14:47:25 -05:00
Thomas Hallock 91154d9364 fix(rithmomachia): add missing i18next dependencies
Added i18next and react-i18next to package.json to fix Docker build failure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 20:32:01 -05:00
Thomas Hallock d568955d6a feat(arcade): add yjs-demo collaborative game and Yjs persistence layer
- Add yjs-demo arcade game with collaborative state management
- Add Yjs persistence layer for real-time sync
- Update socket server with Yjs support
- Update Rithmomachia game component
- Add yjs type definitions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 09:46:20 -05:00
Thomas Hallock c367e0ceec feat(card-sorting): add react-spring animations for real-time sync
Add smooth physics-based animations for card and arrow movements:
- Add @react-spring/web dependency
- Create AnimatedCard component with spring animations
- Create AnimatedArrow component with spring animations
- Add viewport resize handling with debounced isResizing flag
- Conditionally disable animations during drag and resize (immediate mode)
- Enable spring animations only for socket position updates
- Add throttled position syncing (100ms) during drag operations
- Convert all positioning to viewport percentages (0-100)
- Track viewport dimensions and reposition cards on resize

Cards and arrows now smoothly animate when positions update from other
connected windows, while maintaining instant feedback during local
drag operations and viewport resizes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:33:30 -05:00
Thomas Hallock 646a4228d0 fix(qr-button): improve layout and z-index
- Stack room code and share link vertically on left
- Place square QR button on right, spanning both rows
- Show mini QR code (40px) in button instead of emoji
- Fix popover z-index to appear above dropdown menu (z: 10000)
- Reduce button padding for more compact appearance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock e711c52757 feat(homepage): add interactive draggable flashcards with physics
Add a fun, interactive flashcard display to the homepage's flashcard
generator section. Users can drag and throw 8-15 randomly generated
flashcards around with realistic physics-based momentum.

Features:
- Drag and drop flashcards with mouse/touch
- Throw cards with velocity-based physics
- 8-15 randomly generated flashcards (100-999 range)
- Real AbacusReact components for each card
- Client-side rendering to avoid hydration errors

Technical implementation:
- Uses @use-gesture/react for drag gesture handling
- Uses @react-spring/web for smooth physics animations
- Cards generated client-side with useEffect to prevent SSR mismatch
- Each card maintains its own spring-based position and rotation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 17:37:48 -05:00
Thomas Hallock 22426f677f refactor: remove dead Python bridge and unused packages
Removed abandoned SVG generation code that was never used in production:

**Deleted Files:**
- packages/core/src/bridge.py (302 lines) - Python-shell bridge for SVG generation
- packages/core/client/node/src/soroban-generator-bridge.ts - TypeScript wrapper
- packages/core/client/typescript/ - Entire unused @soroban/client package
- packages/core/client/browser/ - Empty package

**Dependencies Removed:**
- python-shell - Only used by abandoned bridge code
- @types/minimatch - Only needed by removed TypeScript packages
- @soroban/client from apps/web

**Code Cleanup:**
- Simplified packages/core/client/node/src/index.ts exports
- Removed SorobanGeneratorBridge, BridgeFlashcardConfig, BridgeFlashcardResult exports

**Impact:**
- ~800 lines of dead TypeScript code removed
- 302 lines of unused Python code removed
- 2 npm dependencies removed
- Build verified successful - no functionality affected

**What Remains Active:**
- generate.py - PDF generation via Typst CLI (actively used by /api/generate)
- soroban-generator.ts - CLI wrapper for PDF generation
- api.py - Optional FastAPI server
- generate_examples.py - Documentation image generator
- Web app uses @soroban/abacus-react for all SVG rendering

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-18 09:11:59 -05:00
Thomas Hallock 7801dbb25f fix(build): resolve Docker build failures preventing deployment
Fixed two critical issues blocking deployment:

1. **TypeScript build failure**: Added @types/minimatch dependency and created
   proper tsconfig.json files for @soroban/core and @soroban/client packages.
   The DTS build was failing because TypeScript couldn't find the minimatch
   type definitions.

2. **Next.js prerendering error**: Fixed complement-race pages importing from
   wrong provider. Pages were using ./context/ComplementRaceContext but game
   components were using @/arcade-games/complement-race/Provider, causing
   "useComplementRace must be used within ComplementRaceProvider" errors
   during static page generation.

Deployment was blocked for 2 days. Container on NAS is from Oct 16th while
latest commits are from Oct 18th.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-18 08:12:41 -05:00
Thomas Hallock e135d92abb refactor(db): remove database schema coupling for game names
BREAKING CHANGE: Database schemas now accept any string for game names

This implements Critical Fix #1 from AUDIT_2_ARCHITECTURE_QUALITY.md

Changes:
- Remove hardcoded enums from all database schemas
- arcade-rooms.ts: gameName now accepts any string
- arcade-sessions.ts: currentGame now accepts any string
- room-game-configs.ts: gameName now accepts any string

Runtime Validation:
- Add isValidGameName() helper to validate against registry
- Add assertValidGameName() helper for fail-fast validation
- Update settings API to use runtime validation instead of hardcoded array

Benefits:
 No schema migration needed when adding new games
 No TypeScript compilation errors for new games
 Single source of truth: validator registry
 "Just register and go" - no database changes required

Migration Impact:
- Existing data is compatible (strings remain strings)
- No data migration needed
- TypeScript will now allow any string, but runtime validation enforces correctness

This eliminates the most critical architectural issue identified in the audit.
Future games can be added by:
1. Register validator in validators.ts
2. Register game in game-registry.ts
That's it! No database schema changes needed.
2025-10-15 21:17:00 -05:00
Thomas Hallock de30bec479 feat(arcade): add modular game SDK and registry system
Create foundation for modular arcade game architecture:

**Game SDK** (`/src/lib/arcade/game-sdk/`):
- Stable API surface that games can safely import
- Type-safe game definition with `defineGame()` helper
- Controlled hook exports (useArcadeSession, useRoomData, etc.)
- Player ownership and metadata utilities
- Error boundary component for game crashes

**Manifest System**:
- YAML-based game manifests with Zod validation
- Game metadata (name, icon, description, difficulty, etc.)
- Type-safe manifest loading with `loadManifest()`

**Game Registry**:
- Central registry for all arcade games
- Explicit registration pattern via `registerGame()`
- Helper functions to query available games

**Type Safety**:
- Full TypeScript contracts for games
- GameValidator, GameState, GameMove, GameConfig types
- Compile-time validation of game implementations

This establishes the plugin system for drop-in arcade games.
Next: Create demo games to exercise the system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 18:09:17 -05:00
Thomas Hallock a74b96bb6f fix: replace isLocked with accessMode and add bcryptjs
- Updated all test files to use accessMode instead of isLocked field
- Fixed room-manager tests to reflect new access control schema
- Installed bcryptjs dependency for password hashing
- All access mode TypeScript compilation errors resolved

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 19:44:14 -05:00
Thomas Hallock bda5bc6c0e fix: prevent database imports from being bundled into client code
**Problem:**
- player-ownership.ts imported drizzle-orm and @/db at top level
- When RoomMemoryPairsProvider imported client-safe utilities, Webpack bundled ALL imports including database code
- This caused hydration error: "The 'original' argument must be of type Function"
- Node.js util.promisify was being called in browser context

**Solution:**
1. Created player-ownership.client.ts with ONLY client-safe utilities
   - No database imports
   - Safe to import from 'use client' components
   - Contains: buildPlayerOwnershipFromRoomData(), buildPlayerMetadata(), helper functions

2. Updated player-ownership.ts to re-export client utilities and add server-only functions
   - Re-exports everything from .client.ts
   - Adds buildPlayerOwnershipMap() (async, database-backed)
   - Safe to import from server components/API routes

3. Updated RoomMemoryPairsProvider to import from .client.ts

**Result:**
- No more hydration errors on /arcade/room
- Client bundle doesn't include database code
- Server code can still use both client and server utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-10 11:40:46 -05:00
Thomas Hallock 83b9a4d976 fix: compile TypeScript server files to JavaScript for production
- Add tsconfig.server.json to compile server-side TypeScript
- Install tsc-alias to resolve path aliases (@/*) in compiled JS
- Update build script to run tsc + tsc-alias before Next.js build
- Update dev script to compile server files before starting
- Remove tsx runtime dependencies from server.js
- Add compiled JS files for socket-server, db, and arcade modules

This enables production builds to run with pure Node.js without
requiring tsx or ts-node at runtime, as required for Docker deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-10 07:55:18 -05:00
Thomas Hallock eedce28572 feat: remove typst dependencies
Remove @myriaddreamin/typst-* packages that are no longer needed.
This eliminates Docker overlay conflicts with hoisted node_modules.

Removed packages (-365):
- @myriaddreamin/typst-all-in-one.ts
- @myriaddreamin/typst-ts-renderer
- @myriaddreamin/typst-ts-web-compiler
- @myriaddreamin/typst.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 10:22:48 -05:00
Thomas Hallock fa4547543d fix: add @types/minimatch to abacus-react devDependencies
- TypeScript was looking for minimatch type definitions
- Hoisted mode made this implicit dependency explicit
- Fixes abacus-react build failure in CI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 09:47:04 -05:00
Thomas Hallock 480960c2c8 fix: regenerate lockfile with node-linker=hoisted from scratch
- Delete and regenerate pnpm-lock.yaml to ensure clean state
- All deps now properly hoisted to root node_modules
- conventional-changelog-conventionalcommits now accessible

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 09:32:21 -05:00
Thomas Hallock 51bf448c9f fix: regenerate lockfile with correct dependency order
- Remove and regenerate pnpm-lock.yaml to match exact package.json state
- Fixes ERR_PNPM_OUTDATED_LOCKFILE errors in CI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 09:10:25 -05:00
Thomas Hallock 4ab1aef9b8 fix: regenerate pnpm lockfile for pnpm 9 compatibility
- Completely regenerate pnpm-lock.yaml with pnpm 9.15.4
- Fixes ERR_PNPM_OUTDATED_LOCKFILE for dependency order changes
- pnpm 9 is stricter about matching dependency specs order

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 09:07:51 -05:00
Thomas Hallock 7ba746b6bd fix: update lockfile and fix Makefile paths
- Update pnpm-lock.yaml with new semantic-release dependencies
- Fix Makefile paths to use packages/core/src/ instead of src/
- All Python scripts now reference correct monorepo structure

Fixes:
- ERR_PNPM_OUTDATED_LOCKFILE in CI workflows
- Missing generate_examples.py in verify-examples workflow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 09:05:41 -05:00
Thomas Hallock 22541df99f fix: use UUID player IDs in session creation fallback
- Changed CreateSessionOptions.activePlayers from number[] to string[]
- Updated socket-server.ts fallback from [1] to [data.userId]
- Added debug logging to validateFlipCard to diagnose turn validation issues

This ensures that when a session is created without explicit activePlayers,
it uses the actual UUID of the requesting player instead of the numeric value 1.
2025-10-06 13:04:33 -05:00
Thomas Hallock 5d5afd4e68 feat: set up Drizzle ORM with SQLite database
Phase 1.1 Complete: Database & Auth Infrastructure

- Configure Drizzle with SQLite and better-sqlite3
- Create schema for users, players, and user_stats tables
- Set up database client with foreign keys and WAL mode enabled
- Add migration runner and package.json scripts
- Generate initial migration (0000_third_carnage.sql)

Database Features:
- Users table with guestId for guest sessions
- Players table with userId FK (cascade delete)
- UserStats table with userId FK (cascade delete)
- Indexes on foreign keys for performance
- Type-safe schema with Drizzle ORM

Testing:
- 20 unit + e2e tests all passing
- Schema validation tests
- Migration idempotency tests
- Foreign key constraint tests
- Cascade delete tests

Scripts added:
- pnpm db:generate - Generate migration from schema
- pnpm db:migrate - Run pending migrations
- pnpm db:push - Push schema directly (dev)
- pnpm db:studio - Visual DB browser
- pnpm db:drop - Drop migration (dev)

User tests verified:
 Migration runs successfully
 Database tables created with correct schema
 Migration is idempotent (can run multiple times)
2025-10-05 17:01:27 -05:00
Thomas Hallock a3878a8537 feat: add React Query setup with api helper
- Install @tanstack/react-query
- Create QueryClientProvider in ClientProviders with stable client instance
- Add queryClient.ts with createQueryClient() and api() helper
- Add api() helper that wraps fetch with automatic /api prefix
- Add example.ts with complete CRUD hook examples
- Configure sensible defaults (5min staleTime, retry once)

All API routes are now prefixed with /api automatically via api() helper.
2025-10-05 16:55:03 -05:00
Thomas Hallock 42b73cf8ee chore: add nanoid dependency
Add nanoid for generating universally unique player IDs
2025-10-04 17:06:53 -05:00
Thomas Hallock a935e5aed8 fix: resolve TypeScript errors in PlayerStatusBar component
- Fix duplicate color properties in single player mode styling
- Fix className prop passing to css() function in both single and multiplayer modes
- Replace undefined 'super-bounce' animation with 'gentle-bounce'

The make-plural pluralization integration is working correctly with proper
display of "1 pair" vs "2 pairs", "1 move" vs "3 moves", etc.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 13:21:45 -05:00