The Ingest page held its 'compiling' flag in local component state, so
routing away and back re-enabled the Compile button while the worker
lock was still held — a second click then 409'd (reported by
@CuprumBuddy in #6, split into #7).
Backend:
- New GET /api/worker/status returning {busy: bool} derived from
tools.worker.job_lock.locked(). Gated by @require_auth (codex first-
pass flagged it as info leak on authed deployments) — no-op
decorator when LLMBASE_API_SECRET is unset, so local/dev mode is
unchanged.
Frontend:
- Ingest.tsx polls /api/worker/status on mount and recovers the
'compiling' state if the lock is held. A 409 from POST /api/compile
(ApiError with status 409, newly exposed via a typed ApiError class
in lib/api.ts) falls into the same polling path rather than flashing
'Compilation failed'.
- mounted-ref guard around every post-await setState site in Ingest.tsx
(mount probe, poll loop, loadDocs, handleIngest, handleCompile,
viewRaw) — prevents the classic 'setState after unmount' leak that
codex's second pass flagged on the mount probe and then again on
loadDocs/ingest/preview.
- Polling caps at 5 consecutive failures so a missing/unauth status
endpoint can't strand the UI in 'Compiling…' forever.
Tests: 128 pass (+1 worker-status reflects-lock test, +1 auth-gate
test). Frontend vite build clean. Codex review LGTM on third pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>