- 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>
Implements a unified banner that seamlessly animates between positions:
- Full banner in content area (Dashboard, Summary pages)
- Compact banner in nav slot (other practice pages)
- Smooth React Spring animation when navigating between pages
New files:
- SessionModeBannerContext: manages slot registration and bounds tracking
- ProjectingBanner: animated portal banner using React Spring
- CompactBanner: condensed single-line variant for nav slot
- PracticeLayout: wrapper component with provider
- ProjectingBanner.stories: interactive demos showcasing transitions
Modified:
- PracticeSubNav: removed Start Practice button, added NavBannerSlot
- DashboardClient/SummaryClient: wrapped with provider, use ContentBannerSlot
- zIndex constants: added SESSION_MODE_BANNER layer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Add @media (max-width: 400px) breakpoints to all three banner components:
- RemediationBanner: smaller padding, icon size, font sizes, button
- ProgressionBanner: smaller padding, icon size, font sizes, button
- MaintenanceBanner: smaller padding, icon size, font sizes, button
Also adds minWidth: 0 to text containers to prevent overflow on small screens.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now that the Remediation CTA prominently displays weak skills,
the duplicate "Targeting:" and "Focusing on weak skills:" sections
in the config panel are no longer needed.
Removed:
- Target skills summary in collapsed view
- Target skills info in expanded config panel
- Unused targetSkillsInfo useMemo
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a student is in remediation mode (has weak skills to strengthen),
the StartPracticeModal now shows a special amber-themed CTA similar to
the tutorial CTA:
- 💪 "Time to build strength!" heading
- Lists weak skills with pKnown percentages
- "Start Focus Practice →" amber button
- Shows up to 4 skills with "+N more" overflow
Includes Storybook stories for:
- Single weak skill
- Multiple weak skills (2)
- Many weak skills (6, with overflow)
- Dark theme variant
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The session planner now accepts an optional sessionMode parameter that:
- Uses pre-computed weak skills from SessionMode (remediation mode)
- Eliminates duplicate BKT computation between UI and problem generation
- Ensures "no rug-pulling" - what the modal shows is what configures problems
Changes:
- session-planner.ts: Accept sessionMode, use getWeakSkillIds() when provided
- useSessionPlan.ts: Accept sessionMode in generateSessionPlan function
- plans/route.ts: Pass sessionMode from request body to planner
- StartPracticeModal.tsx: Pass sessionMode when generating plan
- index.ts: Export SessionMode types from curriculum module
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Creates a single source of truth for practice session decisions:
- SessionMode types: remediation, progression, maintenance
- getSessionMode() centralizes BKT computation
- SessionModeBanner component displays context-aware messaging
- useSessionMode() hook for React Query integration
Updates Dashboard, Summary, and StartPracticeModal to use SessionMode,
eliminating the "three-way messaging" problem where different parts of
the UI showed conflicting skill information.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds interpolation utilities and a celebration banner component that
smoothly morphs between celebration and normal states over 60 seconds.
🤫🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Full-screen mode at ≤700px height for iPhone SE support
- Two-column grid layout for settings in landscape mode
- Integrated tutorial CTA: combines unlock banner + start button
- Fixed collapsed mode clipping of target skills section
- Made "focusing on weak skills" visible on all screen sizes
- Fixed duplicate CSS media query breakpoints
- BKT: changed computeBktFromHistory to accept Partial<BktComputeExtendedOptions>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Documents the critical requirement for --> statement-breakpoint markers
between multiple SQL statements in drizzle migrations. References the
2025-12-18 production outage caused by missing breakpoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Drizzle's better-sqlite3 driver requires --> statement-breakpoint
markers between SQL statements in migration files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Tabs stack vertically on mobile (icon above label) instead of hiding labels
- Summary cards use 2x2 grid on mobile, 4x1 on tablet+
- Skill card grids use smaller min-width on mobile (120px vs 140px)
- Reduced padding throughout on mobile screens
- Section headers and buttons stack vertically on mobile
- History and Notes tabs use responsive padding and font sizes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Student Notes Feature:
- Add notes column to players table with migration
- Create NotesModal component with zoom animation from student tile
- Add notes button on each student card in StudentSelector
- Support viewing and editing notes directly in modal
- Fix modal reopening bug with pointerEvents during animation
- Fix spring animation to start from clicked tile position
BKT & Curriculum Improvements:
- Add configurable BKT thresholds via admin settings
- Add skill anomaly detection API endpoint
- Add next-skill recommendation API endpoint
- Add problem history API endpoint
- Improve skills page with BKT classifications display
- Add skill tutorial integration infrastructure
Dashboard & Session Improvements:
- Enhanced dashboard with notes tab
- Improved session summary display
- Add StartPracticeModal stories
Test Infrastructure:
- Add seedTestStudents.ts script for BKT manual testing
- Add generateTrajectoryData.ts for simulation data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
Replace manual useLayoutEffect + resize listener with react-use-measure
hook for cleaner reactive measurement of takeover container bounds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
DashboardClient had 3 direct fetch() calls that bypassed React Query:
- handleStartOver (abandon session)
- handleSaveManualSkills (set mastered skills)
- handleRefreshSkill (refresh skill recency)
These used router.refresh() to update data, which didn't reliably
update the React Query cache, causing stale UI state.
Fix:
- Add useSetMasteredSkills and useRefreshSkillRecency hooks
- Use useActiveSessionPlan with server props as initial data
- Replace direct fetch with mutation hooks
- Remove router.refresh() calls - React Query handles cache invalidation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add session 0 data to show initial mastery state before practice
- Single Skill tab: line thickness based on skill tier, category average toggles
- All Skills tab: session 0 for ghost lines and averages
- Fix broken GitHub link (was placeholder "...")
- Add source code links to test files that generate chart data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New chart design with multiple visual encodings:
- Ghost lines (40% opacity) show individual skill trajectories
- Green spectrum for Adaptive, gray spectrum for Classic
- Darker shades = later in pedagogical sequence
- Line thickness encodes skill difficulty:
- 1px: basic skills
- 1.5px: five-complements
- 2px: ten-complements (friends of 10)
- 2.5px: cascading/multi-place regrouping
- 4px: average line (full opacity, on top)
- Clear legend showing Adaptive (avg) vs Classic (avg)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaced cluttered 12-line chart with clean 2-line comparison:
- Green line: Average mastery across all skills (Adaptive mode)
- Gray line: Average mastery across all skills (Classic mode)
- Clear legend with Adaptive/Classic labels
- Area fill for visual distinction
- Tooltip shows both values plus advantage in pp
Much easier to see that Adaptive consistently outpaces Classic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed from heading-based injection to explicit marker comments:
- Markers like <!-- CHART: ValidationResults --> in markdown
- Charts now appear after explanatory text, not directly under headings
- Gives explicit control over chart placement in the document flow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed "All Skills" tab to display both modes simultaneously:
- Solid lines = Adaptive mode (with circle markers)
- Dashed lines = Classic mode (no markers)
- Same color = same skill
- Tooltip shows both values with diff highlighted
This makes comparison much easier than toggling between modes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The JSON was stale - regenerated from the correct 6-skill A/B test
snapshot showing adaptive wins 4-0 at 50% and 6-0 at 80%.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Explain the three classification zones (Struggling, Learning, Automated)
and their P(known) thresholds before showing the visualization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'adaptive-bkt' mode using BKT for both skill targeting AND cost
calculation (previously BKT was only used for targeting)
- Make adaptive-bkt the default problem generation mode
- Fix session-planner to include adaptive-bkt in BKT targeting logic
- Add fatigue tracking to journey simulator (sum of skill multipliers)
- Add 3-way comparison test (classic vs adaptive vs adaptive-bkt)
Validation results show both adaptive modes perform identically for
learning rate (25-33% faster than classic). The benefit comes from
BKT targeting, not the cost formula - using BKT for both simplifies
the architecture with no performance cost.
UI changes:
- Simplify Problem Selection to two user-friendly options:
"Focus on weak spots" (recommended) and "Practice everything"
- Remove jargon like "BKT" and "fluency" from user-facing labels
Blog post updated with 3-way comparison findings and unified
BKT architecture documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add validation section with convergence speed comparison results
- Document adaptive skill targeting architecture (separate from cost calculation)
- Add per-skill assessment methodology that doesn't pollute learning state
- Include test results: adaptive reaches 80% mastery faster in 9/9 scenarios
- Update abstract and summary with key findings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comprehensive test harness for comparing BKT-driven adaptive mode vs
classic mode using simulated students with Hill function learning.
Key components:
- SimulatedStudent: Exposure-based learning model with conjunctive
skill probability (P = product of individual skill probabilities)
- JourneyRunner: Runs multi-session practice journeys
- Per-skill deficiency profiles: 32 skills × 3 learner types (96 profiles)
- Per-skill assessment: Measures exposure and mastery on specific skills
WITHOUT learning during assessment
Learner types calibrated for gradual learning over 12 sessions:
- Fast: K=25, n=2.0 (~75 exposures for 90% mastery)
- Average: K=40, n=2.5 (~120 exposures for 90% mastery)
- Slow: K=60, n=3.0 (~150 exposures for 90% mastery)
Key finding: When measuring the RIGHT metric (deficient skill exposure
and mastery), adaptive mode wins 10/15 comparisons vs classic:
- Avg deficient skill exposure: Adaptive=189.6 vs Classic=180.6
- Avg deficient skill mastery: Adaptive=94.9% vs Classic=90.8%
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Validates that the problem generator correctly responds to targetSkills
constraints:
- With targeting: 100% of problems include the target skill
- Without targeting: ~20% include the skill (baseline random chance)
Tests multiple skills across categories (basic, fiveComplements,
tenComplements) with deterministic seeding for reproducibility.
This test helped identify that the issue with adaptive mode wasn't in
the problem generator itself, but in how targetSkills was being set
upstream in session-planner.ts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Validates BKT's ability to identify weak skills using the real problem
generator with deterministic seeding:
- Generates 15,000+ problems covering all 34 skills (400+ per skill)
- Tests each skill by answering 200 correctly and 200 incorrectly
- Verifies BKT identifies each skill as weak (P(known) < 0.6)
- Achieves 100% identification accuracy with sufficient data
Key findings:
- With 100 problems per skill: 82.4% accuracy (6 skills escaped due to
conjunctive model blame distribution)
- With 400 problems per skill: 100% accuracy (all skills correctly
identified as weak)
This confirms BKT's conjunctive model works correctly - it just needs
sufficient data to overcome blame distribution effects when skills
co-occur.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BKT estimates power the Skills Dashboard display only. Problem generation
uses separate fluency states (effortless/fluent/rusty/practicing) from
PlayerSkillMastery records, not BKT P(known) estimates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Describes the pattern tracing system for soroban practice:
- Soroban pedagogy as visual-motor patterns drilled to automaticity
- Simulation-based pattern tagging at problem-generation time
- Conjunctive BKT with probabilistic blame distribution
- Evidence quality weighting (help level, response time)
- Automaticity-aware problem complexity budgeting
- Honest uncertainty reporting with confidence intervals
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add new Skills Dashboard at /practice/[studentId]/skills that provides:
- Per-skill performance tracking with problem history drill-down
- Fluency state categorization (practicing, fluent, effortless, rusty)
- Skills grouped by category (basic, five/ten complements, etc.)
Use conservative presentation to honestly represent skill data:
- Show "Correct: N" and "In errors: M" instead of misleading "Accuracy: X%"
- Label sections "Appear Frequently in Errors" instead of "Need Intervention"
- Add disclaimer: errors may have been caused by other skills in the problem
This addresses the epistemological issue that incorrect answers only tell us
ONE OR MORE skills failed, not which specific skill(s) caused the error.
Files:
- New: SkillsClient.tsx, skills/page.tsx (Skills Dashboard)
- Updated: DashboardClient.tsx (link to skills page)
- Updated: SkillPerformanceReports.tsx (honest framing)
- Updated: session-planner.ts (getRecentSessionResults for problem history)
- Updated: server.ts (re-export new function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix JSX gotcha where `problemHeight && <Component />` would render "0"
when problemHeight is 0. Changed to `(problemHeight ?? 0) > 0 &&` which
always evaluates to a boolean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SessionMoodIndicator with streak animations and touch-friendly popover
- Consolidate transport controls (pause/resume/browse/end) into dropdown menu
- Remove summary section from SessionProgressIndicator (moved to mood tooltip)
- Add DetailedProblemCard with skill annotations and complexity breakdown
- Add autoPauseCalculator for timing threshold calculations
- Add 0.75 opacity to zero-cost skill pills for reduced visual noise
- Clean up unused timing/estimate code from progress indicator
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add PracticePreview component that allows practicing any problem while
in browse mode without affecting session state. The practice panel
displays inline below the problem card with a clear header indicating
it doesn't affect the session, preventing UX confusion.
- Add PracticePreview component with keyboard and numpad input support
- Add inline mode to PracticePreview for embedded display
- Update BrowseModeView to show practice panel below problem card
- Toggle button switches between "Practice This Problem" / "Close Practice Panel"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Browse Mode:
- Add SessionProgressIndicator with collapsible sections for practice/browse modes
- Add BrowseModeView for reviewing problems during practice
- Navigation via clicking progress indicator slots in browse mode
- "Practice This Problem" button to exit browse mode at current problem
- Collapse non-current sections in practice mode (shows ✓count or problem count)
SpeedMeter:
- Add actual time labels (0s, ~Xs avg, Xs pause) positioned under markers
- Extend scale to 120% of threshold so threshold marker isn't always at edge
- Kid-friendly time formatting (8s, 30s, 2m)
- Label overlap detection - combines labels when mean is close to threshold
- Remove unused averageLabel/fastLabel/slowLabel props
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The problem generator was failing with ProblemGenerationError when
minComplexityBudgetPerTerm was set (e.g., challenge slots requiring
complexity >= 1). The issue: skill complexity depends on abacus state,
not just the term value. Adding +4 from 0 is basic (cost 0), but adding
+4 from 7 triggers fiveComplements (cost 1).
The old algorithm filtered terms by minBudget during collection, causing
empty candidate lists when no term could meet the budget at that state.
Fix: Two-phase approach in collectValidTerms() that categorizes ALL
valid terms into meetsMinBudget and belowMinBudget arrays. The selection
prefers high-cost terms but gracefully falls back to lower-cost terms
when the budget is impossible to meet at the current abacus state.
Also adds 31 comprehensive tests covering state-dependent skill
detection, graceful fallback, edge cases, stress tests (1000 problems),
and performance verification.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove console.log statements added during production issue debugging.
The circular import issue causing REINFORCEMENT_CONFIG.creditMultipliers
to be undefined has been fixed. Retain console.error statements for
actual error conditions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adding logging at:
1. fluency-thresholds.ts module load time (before and after exports)
2. progress-manager.ts import time (to see what was imported)
This will help identify if:
- The module isn't loading at all
- The config object is partially defined
- There's a circular dependency timing issue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The issue was that progress-manager.ts was importing REINFORCEMENT_CONFIG
from @/db/schema/player-skill-mastery, which re-exported it from
@/lib/curriculum/config. This created a circular dependency that caused
the config object's creditMultipliers property to be undefined in production.
Root cause found via logging:
```
REINFORCEMENT_CONFIG.creditMultipliers=undefined, helpLevel=0
```
Fix:
- Import REINFORCEMENT_CONFIG directly from @/lib/curriculum/config/fluency-thresholds
- Remove unused re-export from player-skill-mastery.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This is the function that's actually failing according to the previous
logs. Adding logging around:
- getSkillMastery lookup
- REINFORCEMENT_CONFIG access
- Database update/insert operations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Move SessionPausedModal inside ActiveSession component (single source of truth)
- Replace studentName prop with student: StudentInfo for modal display
- Remove sessionRef imperative handle (no longer needed)
- Fix auto-pause re-triggering immediately after resume by resetting timer
- Update PracticeClient to remove duplicate modal and pause state
- Update stories to use new student prop
Previously, there were two pause states that could get out of sync:
1. PracticeClient's isPaused (controlled modal visibility)
2. ActiveSession's internal phase.phase === 'paused' (controlled input)
Now ActiveSession owns both the modal and the pause state, eliminating the sync issue.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When the auto-pause modal was dismissed via the Resume button, the modal
would hide but input would remain blocked. This was because:
1. PracticeClient has isPaused state (controls modal visibility)
2. ActiveSession has internal phase.phase='paused' (controls input acceptance)
When the modal's Resume button was clicked, only PracticeClient's state
was updated, leaving ActiveSession stuck in 'paused' phase.
Fix: Add sessionRef prop to ActiveSession that exposes resume/pause
handlers, allowing PracticeClient to trigger ActiveSession's internal
resume when the modal is dismissed.
Long-term: Consider moving the modal inside ActiveSession so there's
a single source of truth for pause state.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add detailed try-catch logging around each step in recordSlotResult:
- Before/after calculateSessionHealth
- Before/after Drizzle update
- Before/after recordSkillAttemptsWithHelp
This will pinpoint exactly where the "[0]" error occurs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add detailed logging and more defensive checks to help debug production 500 errors:
- Log entry point with plan ID
- Wrap getSessionPlan in try-catch for better error messages
- Log plan state (status, partIndex, slotIndex, parts/results arrays)
- Validate slots array exists on current part
- Validate results array exists
- All checks provide descriptive error messages
This should help identify exactly where the "Cannot read properties of undefined (reading '0')" error is coming from.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add robust error handling to recordSlotResult to prevent cryptic
"Cannot read properties of undefined" errors:
- Check that plan.parts exists and is a valid array before indexing
- Validate currentPartIndex is within valid bounds
- Ensure the database update returned a result
These checks provide clearer error messages when data is corrupted
or in an invalid state, helping diagnose production issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>