fix(cleanup): library scans survive navigation, reconnect on return
CI / frontend-build (push) Successful in 24s
CI / lint (push) Successful in 2s
CI / backend-lint-and-test (push) Successful in 11s
CI / integration (push) Successful in 2m56s

The transparency / single-color audit cards held the run + poll timer in
local component state, so navigating away destroyed both and onMounted never
reconnected — the Celery scan kept running and writing LibraryAuditRun, but
the UI forgot it. Now each card, on mount, fetches its rule's latest run
(GET /api/cleanup/audit?rule=<rule>&limit=1) and rehydrates: shows progress +
resumes polling if still running, or shows the completed result (ready/applied/
error) so the operator can act on it after returning. Adds the ?rule= filter
to the audit-history endpoint + cleanup store latestAuditForRule().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 16:55:20 -04:00
parent 91b0145bc8
commit 5a6a95682d
5 changed files with 58 additions and 6 deletions
+21
View File
@@ -155,6 +155,27 @@ async def test_audit_history_returns_recent_runs(client, db):
assert len(body["runs"]) >= 3
@pytest.mark.asyncio
async def test_audit_history_filters_by_rule(client, db):
db.add(LibraryAuditRun(
rule="transparency", params={"threshold": 0.9},
status="applied", matched_ids=[], finished_at=datetime.now(UTC),
))
db.add(LibraryAuditRun(
rule="single_color", params={"threshold": 0.95, "tolerance": 30},
status="ready", matched_count=2, matched_ids=[1, 2],
finished_at=datetime.now(UTC),
))
await db.commit()
# ?rule=&limit=1 → just THIS rule's latest run (the card-reconnect query).
resp = await client.get("/api/cleanup/audit?rule=single_color&limit=1")
assert resp.status_code == 200
runs = (await resp.get_json())["runs"]
assert len(runs) == 1
assert runs[0]["rule"] == "single_color"
assert runs[0]["matched_count"] == 2
@pytest.mark.asyncio
async def test_audit_apply_with_token_deletes(client, db, tmp_path):
rec = await _seed_image(db, tmp_path, w=100, h=100, name="apply.png")