Fixes UnboundLocalError crash when deck_row is None by returning an
empty list instead of falling through to a query with an unbound deck_id.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GET /api/lab/result: Starlette's JSONResponse uses allow_nan=False,
so NaN/Infinity floats from simulation output cause a ValueError crash.
Add _sanitize_floats() to replace non-finite floats with null before
returning. Also wrap json.load in try/except for better error reporting.
- POST /api/lab/precons/install-batch: Frontend sends {"names": [...]}
but backend expected {"fileNames": [...]}. Accept both field names.
- POST /api/lab/precons/install: Same mismatch — frontend sends {"name"}
but backend expected {"fileName"}. Accept both field names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same pattern as the previous _resolve_forge_jar() fix — when --forge-dir
is not passed via CLI or FORGE_DIR env var, auto-detect the Forge
installation directory by:
1. Deriving from the already-resolved forge_jar path (parent of target/)
2. Checking common sibling directories (forge/, forge-repo/)
3. Checking platform user data dirs (~/.forge, ~/Forge, %APPDATA%/Forge)
Also audited all other CFG fields — forge_jar, forge_decks_dir, lab_jar,
port, results_dir all already have proper defaults or auto-resolve
fallbacks. Added Forge Dir, Lab JAR, and Results Dir to startup log
output for better diagnostics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The port of run_batch_subprocess from lab_api_backup.py to
services/forge_runner.py truncated the function signature to 8 params +
**kwargs, but the route handler in routes/lab.py passes 13 positional
arguments, causing TypeError at runtime when POST /api/lab/start fires.
Restore all 13 explicit parameters (policy_style, policy_greedy,
ai_simplified, ai_think_time_ms, max_queue_depth) to match the caller
and pass them as keyword args to build_java_command. Also compute
policy_server from CFG.port and add error handling, matching the
original backup implementation.
Additionally, _run_process_blocking was writing to wrong BatchState
attribute names (state.status, state.games_done, state.games_total,
state.throughput, state.log, state.started_at, state.ended_at) instead
of the correct ones (state.running, state.completed_games,
state.total_games, state.sims_per_sec, state.log_lines, state.elapsed_ms).
This caused the /api/lab/status endpoint to never see progress updates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>