- except clause in cancel_benchmark/cancel_finetune narrowed from Exception
to _subprocess.TimeoutExpired (C1)
- _cancelled_jobs.discard() called after registering new proc to prevent
a stale flag from a prior run masking errors (I2)
- local `import subprocess` removed from run_benchmark and
run_finetune_endpoint; all Popen calls updated to _subprocess.Popen (I1)
- test patch targets updated from subprocess.Popen to app.api._subprocess.Popen;
cancelled-event tests updated to set flag in proc.wait() side-effect so
the discard-on-new-run logic is exercised correctly
Adds POST /api/benchmark/cancel and POST /api/finetune/cancel endpoints
that terminate the running subprocess (kill on 3s timeout), and updates
the run generators to emit a cancelled SSE event instead of error when
the job was intentionally stopped.
Two bugs fixed:
1. Blank white page after vue SPA rebuild: browsers cached old index.html
referencing old asset hashes. Assets are deleted on rebuild, causing
404s for JS/CSS -> blank page. Fix: serve index.html with
Cache-Control: no-cache so browsers always fetch fresh HTML.
Hashed assets (/assets/chunk-abc123.js) remain cacheable forever.
2. Queue draining to empty on skip/discard: handleSkip and handleDiscard
never refilled the local queue buffer. After enough skips, store.current
went null and the empty state showed (blank-looking). Fix: both handlers
now call fetchBatch() when queue drops below 3, matching handleLabel.
Also: sync classifier_adapters LABELS to match current 10-label schema
(new_lead + hired, remove unrelated).
48 Python tests pass, 48 frontend tests pass.
- Add _item_id() (content hash) + _normalize() to map legacy JSONL fields
(from_addr/account/no-id) to Vue schema (from/source/id)
- All mutating endpoints now look up by _normalize(x)[id] — handles both
stored-id (test fixtures) and content-hash (real data) transparently
- Change uvicorn bind from 127.0.0.1 to 0.0.0.0 so LAN clients can connect
status.write() per email grows the log unboundedly on big pulls.
Now uses status.empty() to create one updatable slot; per-email
progress overwrites it, cleared after each account completes.
Per-account summaries still use status.write() (one line each).