Background Maia + Stockfish analysis during drill play#260
Merged
Conversation
The previous implementation used a useEffect cleanup to cancel the background Stockfish/Maia analysis loop on every dependency change (including every new move). This killed evaluations mid-stream and marked nodes as queued without completing them. Replaced with a ref-based queue and persistent async loop that only cancels when the drill session itself changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: currentDrillGame state changes on every player/Maia move (updating moves array and playerMoveCount). The cancellation effect depended on currentDrillGame, so every move triggered cleanup which set backgroundCancelledRef=true, killing the loop immediately. Fix: track drill identity by ID instead of the full state object. Only cancel when a genuinely new drill starts. Also stop background analysis when post-drill analysis begins to avoid stockfish contention. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Background loop runs both Maia + Stockfish on drill positions as they're played. When the drill ends, ensureDrillAnalysis: 1. Sets cancelled flag (loop exits after current position) 2. Calls stockfish.stopEvaluation() to abort any in-progress eval 3. Awaits the loop promise to ensure full exit 4. Only then starts its own stockfish work This avoids the concurrent generator bug where the old generator's finally block would clobber the new generator's engine.listen callback, causing the post-drill analysis to hang. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
React runs useEffects in declaration order. The separate cancellation effect was firing AFTER the enqueue effect, clearing the queue that was just populated. Merged both into a single effect so drill-change reset and node enqueuing happen atomically. Also handle drill-cleared case (cancel background when no active drill). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detailed [bg] logs at each stage to diagnose why background analysis doesn't run during drill play. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The queue/loop pattern had too many failure modes (running flags, queue clearing, effect ordering). Replaced with a simple promise chain: each new drill node gets its analysis chained onto a single ref promise. No queue, no running flag, no separate loop callback. - bgChainRef: single promise chain, analysis tasks appended via .then() - bgAnalyzedFensRef: Set tracks which FENs have been scheduled - Drill change: cancel flag + chain reset - stopBackgroundAnalysis: sets cancel + stops stockfish + awaits chain Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two fixes: 1. Wrap each chain step in try/catch so a single error doesn't reject the entire promise chain 2. Don't await the chain when stopping — just signal cancellation and stop stockfish, then proceed. Awaiting was hanging when a step was stuck (e.g., Maia ONNX inference or stockfish generator) Also added more detailed [bg] console logs at each stage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: useAnalysisController's useEngineAnalysis hook auto-runs stockfish on every currentNode change. During drill play, each move synced the node to the analysis controller, which called stockfish.streamEvaluations() — killing the background analysis's in-progress evaluation (the new call's stopEvaluation() terminates the old generator). Fix: only sync currentNode to the analysis controller when analysis is actually active (post-drill continue-analyzing mode), not during active drill play. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The analysis controller's useEngineAnalysis hook has its own internal tree controller that navigates the drill's game tree. Even though we stopped syncing currentNode, the internal controller still tracked tree changes and fired stockfish.streamEvaluations() — which calls stopEvaluation() and kills the background analysis's in-progress evaluation (explaining depth 8 instead of 18). Added an 'enabled' parameter to useEngineAnalysis and useAnalysisController. During drill play (analysisEnabled=false, continueAnalyzingMode=false), both Maia and Stockfish effects in useEngineAnalysis are completely skipped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bgChainRef) to avoid clobbering the single Stockfish WASM instance. Each node is analyzed one at a time (Maia first, then Stockfish).enabledflag touseEngineAnalysisso the analysis controller doesn't auto-fire Stockfish on every board position change during drills, which would steal the engine from background analysis.Key changes
useOpeningDrillController.ts— Background analysis lifecycle (enqueue, cancel on drill change, stop on drill end)useEngineAnalysis.ts— Addedenabledparameter to gate Maia/Stockfish effectsuseAnalysisController.ts— PassesenableEngineAnalysisflag throughopenings/index.tsx— Disables engine analysis during drill play, only syncs nodes when analysis is activeTest plan
🤖 Generated with Claude Code