Skip to content

release: v0.6.6#46

Merged
sudolulo merged 13 commits into
mainfrom
dev
Jun 18, 2026
Merged

release: v0.6.6#46
sudolulo merged 13 commits into
mainfrom
dev

Conversation

@sudolulo

@sudolulo sudolulo commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • Bump version to 0.6.6
  • Lower `MAX_AUTO_IMAGES` default from 20 to 5
  • Replace lockfile auto-update workflow with `uv lock --check` + pre-commit hook

Changes

Changed

  • `MAX_AUTO_IMAGES` default lowered from 20 to 5. 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.

CI / dev tooling

  • `update-lockfile.yml` deleted — was fragile, required special repo permissions, opened bot PRs on every `pyproject.toml` change, and could silently pick up unintended upstream version bumps
  • `uv lock --check` added to `test.yml` — CI now fails fast if the lockfile is out of sync
  • `.githooks/pre-commit` added — automatically runs `uv lock` and stages the result whenever `pyproject.toml` is part of a commit; activated with `git config core.hooksPath .githooks` (documented in CONTRIBUTING.md)

Test plan

  • End-to-end upload test against test Frigate instance: 84/88 images uploaded successfully (4 expected rejections — face too small or Frigate 500)
  • `uv lock --check` catches stale lockfile (verified on PR chore: replace lockfile auto-update with uv lock --check #47 — first run caught the v0.6.6 version bump missing from lockfile)
  • Pre-commit hook auto-stages `uv.lock` on `pyproject.toml` changes

sudolulo added 13 commits June 17, 2026 17:16
Frigate returns HTTP 500 with 'Could not process' when its face detector
cannot find or embed a face in the uploaded crop — this will never succeed
on retry. Previously these were silently logged at DEBUG and retried on
every future run.

- Surface 500 error details inline (same display path as 400)
- Mark 500 + 'could not process' as a permanent rejection so the asset
  is skipped on future runs instead of retried indefinitely
process_face_mode now returns a descriptive string instead of None for
filtered-out faces ("face too small 45x38px, min 90px", "no face
metadata"), so the executor can print a useful reason rather than the
generic "no usable face data".

Also suppresses the InsightFace norm_crop FutureWarning about deprecated
estimate usage, which was noisy at INFO level on every aligned crop.
Smaller default cap is more conservative for new installs and better
reflects the minimum viable training set for Frigate face recognition.
Users who need more can set MAX_AUTO_IMAGES explicitly.
…, CHANGELOG note

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.
…e return type

Use full_body for the 500 'could not process' permanent-rejection check,
consistent with the 400 'face' check on the line above. error_detail is
truncated to 100 chars via the fallback path, which could silently miss
the phrase in a long response body.

Remove | None from process_face_mode return type — every code path returns
tuple[int,int] or str; None is unreachable. Update docstring to match.
- immich_api: .get("items") or [] handles {"items": null} without crashing len()
- immich_api: catch TypeError alongside ValueError in filter_recent_assets for
  timezone-naive fileCreatedAt comparisons
- scheduler: catch SystemExit in addition to KeyboardInterrupt so cli.main()
  cannot kill the long-running scheduler process
- scheduler: reseed croniter from wall-clock time after each run so overrunning
  jobs don't schedule an immediate back-to-back rerun
- config: reject negative YEARS_FILTER values with a warning, reset to default 10
- frigate_api: return True (not False) for empty filenames list — callers cannot
  distinguish no-op from network failure on False
- jobs: warn on unrecognised STRATEGY value instead of silently falling back
- jobs: casefold ONLY_PEOPLE / SKIP_PEOPLE matching so "john doe" matches "John Doe"
- executor: <= → < so a same-score candidate can fill a freed replacement slot
- embeddings: set _insightface_loaded=True on GPU+CPU double-failure to prevent
  N re-init attempts (one per asset) when InsightFace is broken for a whole run
fix: Frigate 500 permanent rejection + 13 correctness bugs
chore: replace lockfile auto-update with uv lock --check
@sudolulo
sudolulo merged commit 0415105 into main Jun 18, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant