chore: the film-making shortcut leaves the server, and failures stop hiding

From the deep review's hygiene list:

- The demo replay (a still recognition replayed as if it were live tracking) moves
  out of app.py into demo_replay.py, and every payload it produces is marked
  `synthetic: true`. It had been committed inside an unrelated feature commit, which
  made a film-making device look like part of the server.
- `/v1/health` reports the OCR engine and whether it is available. Without it an
  operator could not tell a broken OCR from a shelf with no readable tags.
- A failed OCR pass is counted and logged instead of swallowed: `TagService.stats()`
  now carries `passes_failed` and `last_pass_error`.
- The live classification budget goes back to the measured production defaults
  (16 in flight, 2 attempts); a demo walk over a nearly static shelf asks for more
  through `--live-inflight` / `--live-attempts` rather than silently changing the
  default for everyone.

162 tests pass.

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
kiyo9w 2026-09-25 01:30:16 +09:00
parent 99bce4d7bf
commit e67ab8bfb4
5 changed files with 287 additions and 149 deletions

View file

@ -76,7 +76,11 @@ class EngineSettings:
# (21/21 SKUs on image.jpg). hybrid_fast (ORB shortlist) is 3.4x faster but
# agreed with hybrid on only 47% of accepted crops, so it is NOT the default
# and stays available for experiments only (bench_engine.py --compare).
live_inflight: int = 12
# Measured for a moving camera with hybrid classification: 16 in flight keeps
# the queue draining while detection keeps its share of the CPU. A demo walk
# over a nearly static shelf wants more; that is a CLI override, not a default.
live_inflight: int = 16
live_attempts: int = 2
imgsz: int = 640
# 0 -> max(2, cpu_count - 2). Measured default below (see build_default_engine).
classify_workers: int = 5
@ -737,6 +741,7 @@ def settings_from_env(env: Optional[Dict[str, str]] = None) -> EngineSettings:
live_method=env.get("DORAYAKI_LIVE_METHOD", base.live_method),
live_conf=float(env.get("DORAYAKI_LIVE_CONF", base.live_conf)),
live_inflight=int(env.get("DORAYAKI_LIVE_INFLIGHT", base.live_inflight)),
live_attempts=int(env.get("DORAYAKI_LIVE_ATTEMPTS", base.live_attempts)),
detect_conf=float(env.get("DORAYAKI_DETECT_CONF", base.detect_conf)),
)