From 86caffc8d720939e72481f213aff94b6909d3fe7 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 17 Jun 2026 17:31:20 +0000 Subject: [PATCH] =?UTF-8?q?fix:=203=20audit=20findings=20=E2=80=94=20truth?= =?UTF-8?q?y=20skip-reason=20bug,=20500=20match=20consistency,=20CHANGELOG?= =?UTF-8?q?=20note?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. if saved: → if isinstance(saved, tuple): so string skip-reasons from process_face_mode no longer register as successes and create phantom asset_map entries with no JPEG on disk. Dead reason/fallback code in the else branch now correctly handles str and None returns. 2. "could not process" permanent-rejection check now uses error_detail (json message field, falling back to body[:100]) instead of full_body, keeping the match consistent with what is displayed to the user. 3. CHANGELOG [Unreleased] breaking-change note for MAX_AUTO_IMAGES 20→5 so upgrading users know to set the env var if they want the old cap. --- CHANGELOG.md | 4 ++++ winnow/executor.py | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6966e91..92ff442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **`MAX_AUTO_IMAGES` default lowered from 20 to 5** — existing users who have not set this variable and already have more than 5 winnow-managed images in Frigate will find themselves at cap on the next run. With `QUALITY_REPLACEMENT=true` (the default), winnow will attempt to swap weaker images rather than uploading new ones. Set `MAX_AUTO_IMAGES=20` to restore the previous behaviour. + ## [0.6.5] - 2026-06-17 ### Added diff --git a/winnow/executor.py b/winnow/executor.py index 6eb0a9c..5b0aeb6 100644 --- a/winnow/executor.py +++ b/winnow/executor.py @@ -186,12 +186,11 @@ def execute_jobs(jobs: list[dict]) -> None: saved = process_face_mode( img, asset, person, person_dir, count, insightface_app=insightface_app ) - if saved: + if isinstance(saved, tuple): filename = f"{count}.jpg" asset_map[filename] = asset["id"] score_map[filename] = asset.get("quality_score") - if isinstance(saved, tuple): - dims_map[filename] = saved + dims_map[filename] = saved # Time-spread path: compute blur score from the downloaded # image. Capped at 1440px via blur_score_from_image() so the # scale matches the preview thumbnails the embedding path uses @@ -574,7 +573,7 @@ def upload_to_frigate(jobs: list[dict]) -> None: _is_permanent = ( (resp.status_code == 400 and "face" in full_body.lower()) or resp.status_code == 422 - or (resp.status_code == 500 and "could not process" in full_body.lower()) + or (resp.status_code == 500 and "could not process" in error_detail.lower()) ) if _is_permanent: asset_id = asset_map.get(fname)