**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>
Implement hybrid database + application-level enforcement to ensure users
can only be in one room at a time, with graceful auto-leave behavior and
clear error messaging.
## Changes
### Database Layer
- Add unique index on `room_members.user_id` to enforce one room per user
- Migration includes cleanup of any existing duplicate memberships
- Constraint provides safety net if application logic fails
### Application Layer
- Auto-leave logic: when joining a room, automatically remove user from
all other rooms first
- Return `AutoLeaveResult` with metadata about rooms that were left
- Idempotent rejoining: rejoining the same room just updates status
### API Layer
- Join route returns auto-leave information in response
- Catches and handles constraint violations with 409 Conflict
- User-friendly error messages when conflicts occur
### Frontend
- Room list and detail pages handle ROOM_MEMBERSHIP_CONFLICT errors
- Show alerts when user needs to leave current room
- Refresh room list after conflicts to show current state
### Testing
- 7 integration tests for modal room behavior
- Tests cover: first join, auto-leave, rejoining, multi-user scenarios,
constraint enforcement, and metadata accuracy
- Updated existing unit tests for new return signature
## Technical Details
- `addRoomMember()` now returns `{ member, autoLeaveResult? }`
- Auto-leave happens before new room join, preventing race conditions
- Database unique constraint as ultimate safety net
- Socket events remain status-only (joining goes through API)
## Testing
- ✅ All modal room tests pass (7/7)
- ✅ All room API e2e tests pass (12/12)
- ✅ Format and lint checks pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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.
Fix bug where new route passengers would appear on train cars before
all cars from the previous route had exited through the tunnel.
The issue occurred because passengers were switched when trainPosition < 0
(locomotive exits), but train cars trail behind by up to 35% (5 cars × 7%
spacing). This caused new passengers to briefly appear on the old cars that
were still fading out (positions 65-97%).
Solution: Calculate the last car's position and only switch passengers when:
1. Train has reset to start position (trainPosition < 0), OR
2. All cars have fully faded out (lastCarPosition >= 97%)
Changes:
- useTrackManagement: Added maxCars and carSpacing parameters
- Updated passenger display logic to check lastCarPosition >= fadeOutEnd
- SteamTrainJourney: Pass maxCars and carSpacing from useTrainTransforms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove 60-second time limit for infinite gameplay
- Auto-advance to next route upon completion instead of showing modal
- Time-of-day cycle now repeats every 60 seconds indefinitely
- Update documentation to reflect infinite mode behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
After removing @nav parallel routes, all pages were missing navigation.
Added PageWithNav wrapper to main application pages:
- Homepage: 🧮 Soroban Flashcards
- Games listing: 🕹️ Soroban Arcade
- Interactive guide: 📚 Interactive Guide
- Create flashcards: ✨ Create Flashcards
- Game pages already had navigation from previous commit
Each page now has appropriate nav title and emoji displayed in the
mini navigation bar. All navigation is working correctly again.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
- Add new localhost ports for testing and development
- Include additional bash commands for E2E testing and debugging
- Enable Playwright testing and browser automation permissions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Disable npm registry publishing in semantic-release config to avoid NPM_TOKEN requirement
- Enable GitHub Packages publishing with GITHUB_TOKEN authentication
- Update workflow to configure only GitHub Packages registry authentication
- Allow package publishing to GitHub Packages without npm credentials
- This enables automatic publishing to GitHub Packages while npm setup is pending
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Move calculateOptimalGrid function outside useGridDimensions hook
- Fix function scoping issue that caused ReferenceError during useState initialization
- Add safety check for window object in helper function
- Grid layout now properly initializes without runtime errors
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Configure semantic-release for simultaneous publishing to both registries
- Update GitHub Actions workflow with dual authentication setup
- Enhanced documentation across all relevant files
- Package now publishes to both npm and GitHub Packages automatically
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update CONTRIBUTING.md with detailed abacus-react package publishing workflow
- Add prominent NPM publishing section to root README
- Create .claude/AUTOMATED_WORKFLOWS.md for future Claude sessions
- Document commit format requirements: feat(abacus-react): for package releases
- Include troubleshooting info and current status (awaiting NPM_TOKEN)
This ensures future Claude sessions can automatically discover and use the
package publishing workflow without requiring explanation.
- Add semantic-release configuration for abacus-react package with scope-based versioning
- Create GitHub Actions workflow for automated publishing to npm
- Configure package-specific semantic versioning with conventional commits
- Add release scripts and update README with publishing documentation
- Update root release config to exclude abacus-react scope from monorepo releases
- Package releases are triggered by commits with scope 'abacus-react'
BREAKING CHANGE: abacus-react package now has independent versioning from monorepo
- Add comprehensive GitHub Actions workflow for automated Storybook deployments
- Deploy apps/web Storybook to gh-pages/web subdirectory
- Deploy packages/abacus-react Storybook to gh-pages/abacus-react subdirectory
- Create beautiful landing page with navigation to both Storybooks
- Add Component Documentation section to README with direct links
- Support both PR previews and main branch deployments
- Optimize build process with proper dependency management
- Remove unused onConfigurePlayer prop from ChampionArena interface
- Update GameSelector component interactions
- Update Claude settings for development workflow
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Restore @soroban/core and @soroban/client dependencies in apps/web
- Correct workspace configuration to include all existing packages
- Disable problematic example-server.ts to fix TypeScript build
- Update Dockerfile to copy all required package.json files
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update local settings to support provenance system development workflow and testing.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix column indexing bug where tens/ones columns were swapped
- Add boundary checks to prevent values exceeding abacus capacity
- Improve earth and heaven bead click logic with proper place value mapping
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Vitest test framework setup with jsdom environment
- Create memory-quiz-utils.ts with testable prefix matching functions
- Add comprehensive test suite covering:
- Prefix matching logic with found/unfound number exclusion
- Edge cases for input validation
- 55/555 bug scenario reproduction and fix
- Integration test scenarios
Tests currently have 3 failures that need debugging in prefix logic.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix infinite re-rendering in AbacusDisplayContext by removing initialConfig dependency from useEffect
- Resolve dropdown not dismissing on outside clicks by removing conflicting CSS animation
- Add proper event handlers and positioning for dropdown UX
- Maintain form control interactions while allowing dropdown dismissal
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Install concurrently package for running multiple processes
- Update dev script to run both Next.js dev and Panda CSS watch
- Automatically regenerate CSS when styles change during development
- Eliminates need to manually run panda codegen after CSS changes
Dev script now runs:
- Next.js development server
- Panda CSS file watcher for automatic style regeneration
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Generated updated CSS for new layout improvements
- Includes gradient borders, modern styling, and compact spacing
- Ensures all new CSS classes are properly generated
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed path duplication bug in bridge constructor
- Updated bridge to use event-based PythonShell approach
- Updated web preview route to use correct Python script path
- Web app now generates real SVGs from Python/Typst instead of mock SVGs
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove original client/, config/, fonts/, src/, templates/ directories
- Clean up miscellaneous test HTML files
- Maintain clean project structure after reorganization
- All functionality preserved in packages/core
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Persistent reminder to reference rebuild checklist
- Prevents future loss of context and features
- Ensures systematic approach to train-related tasks
🚂 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated local settings to support improved development workflow
and testing capabilities.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
All example images (PNG and SVG formats) have been regenerated to show
the improved heaven bead positioning where inactive heaven beads maintain
the same 19px gap from the reckoning bar as inactive earth beads.
This ensures all documentation examples are consistent with the positioning
fix implemented in commit a048e11 and maintains visual consistency across
all example formats.
Updated images:
- PNG examples: cutting-guides, cutting-registration, grid-6, grid-12, skip-5s
- SVG examples: basic-7, basic-123, circle-25, diamond-25, heaven-earth-78,
minimal-42, place-value-456, square-25
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add permission for git restore command
- Required for git workflow during development
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Generate examples showing cutting guides and registration marks
- Add 'Printing Features' section to README
- Show full-page cutting guides for accurate card separation
- Include example with both cutting guides and registration marks
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Clarify page ordering with detailed comments (fronts on odd, backs on even)
- Add PDF metadata for better document properties
- Improve qpdf linearization with object stream preservation
- Document duplex printing behavior in README
- Ensure consistent front/back pairing with explicit pagebreaks
The PDF now clearly alternates between soroban diagrams (odd pages)
and numerals (even pages) for reliable duplex printing with long-edge
binding.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>