fix: quality replacement slot floor uses deleted file's score not failed candidate's (#27)
* fix: quality replacement slot floor uses deleted file's score not failed candidate's When a blur-score replacement deletes a low-quality Frigate file but the subsequent upload fails, min_quality_score_for_slot was set to candidate_score (the good file that failed to upload). This filtered out any subsequent candidate that didn't beat the failed upload, even if it was better than the file we just deleted — leaving the freed slot unfilled unnecessarily. The comment on the guard already documented the correct intent: 'require the next candidate to beat the deleted file's score'. Fix: use target_score (the deleted file's blur score) as the floor instead of candidate_score. * chore: bump version to 0.5.4
This commit is contained in:
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.5.4] - 2026-06-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Quality replacement slot floor used wrong score**: when a blur-score replacement deleted a low-quality Frigate file but the subsequent upload failed, `min_quality_score_for_slot` was set to the failed candidate's score rather than the deleted file's score. This caused subsequent candidates that were better than the deleted file (but worse than the failed upload) to be skipped, leaving the freed slot unfilled for the rest of that run. Fixed by using `target_score` (deleted file's score) as the floor, matching the documented intent in the surrounding comment.
|
||||
|
||||
## [0.5.3] - 2026-06-14
|
||||
|
||||
### Fixed
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "winnow"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
description = "Selects diverse, high-quality photos from Immich as training data for Frigate face recognition."
|
||||
license = "AGPL-3.0-or-later"
|
||||
requires-python = ">=3.13"
|
||||
|
||||
+1
-1
@@ -464,7 +464,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
remove_frigate_file(name, target_frigate_file)
|
||||
person_has_fscores = has_frigate_scores(name)
|
||||
effective_count -= 1
|
||||
min_quality_score_for_slot = None if using_fscore else candidate_score
|
||||
min_quality_score_for_slot = None if using_fscore else target_score
|
||||
else:
|
||||
logger.warning("Failed to delete %s for %s, skipping replacement", target_frigate_file, name)
|
||||
failed_deletes.add(target_frigate_file)
|
||||
|
||||
Reference in New Issue
Block a user