Commit graph

3 commits

Author SHA1 Message Date
2b4875d77c fix: handle empty-platform captures, no-op fires, and observe races
- IntakeSession.observe_frame now catches ValueError from crop_to_book
  (empty-platform capture), cleans up any orphan wide-image file/dir,
  resets the strategy, and does not advance session state. The error
  is surfaced via a new last_error field.
- /api/observe adds an "error" field to the response when a capture
  fires but fails, instead of an unhandled 500.
- observe_frame only reports fired=True (and only runs capture logic)
  when state is WAITING_FRONT or WAITING_BACK, so a completed book
  left on the platform can no longer produce a no-op "fired" capture
  from an auto-strategy re-triggering.
- observe_frame now holds a per-session threading.Lock for its whole
  body, since the frontend polls /api/observe every ~500ms without
  chaining requests and Catalogue.update_row() does a non-atomic
  read-all-then-rewrite-whole-file rewrite of catalogue.csv.

Adds tests for empty-platform front/back captures and the
BOOK_COMPLETE no-op-fire case, plus an API-level empty-platform test.
2026-07-13 11:22:08 -07:00
7d0bebf16d fix: return structured 503 on camera read failure in /api/observe
Wrap camera.read_frame() call in try/except to catch RuntimeError and
return a 503 Service Unavailable response with structured error JSON
(error + detail fields) instead of letting the exception propagate
as an unhandled 500. This gives kiosk operators a friendly, actionable
error message when the camera becomes unavailable.

Added FailingCamera test fixture and regression test that verifies
the 503 response with expected error details.
2026-07-13 10:58:30 -07:00
ae73ab2329 feat: add FastAPI backend for intake session 2026-07-13 10:51:43 -07:00