chore: bump version to 0.4.0, update changelog and all docs

Finalizes the 0.4.0 release:

- Version bumped to 0.4.0 in pyproject.toml
- CHANGELOG.md: add [0.4.0] section covering Frigate pre-upload scoring,
  quality replacement inversion, bootstrap fix, FRIGATE_SCORE_CEILING,
  ENABLE_FRIGATE_SCORES, removal of post-upload quality gate, and all
  doc/default corrections
- README.md: step 8 updated for dual-mode replacement, FRIGATE_SCORE_CEILING
  and ENABLE_FRIGATE_SCORES added to env var table, MIN_FACE_WIDTH and
  BLUR_THRESHOLD defaults corrected (50→90, 100→120)
- .env.example: FRIGATE_SCORE_THRESHOLD replaced with FRIGATE_SCORE_CEILING;
  QUALITY_REPLACEMENT line added; comments updated to match current semantics
- winnow/executor.py: bootstrap fix — recognize now called for all below-cap
  uploads when ENABLE_FRIGATE_SCORES=true (was gated on CEILING > 0)
- winnow/upload_tracker.py: frigate_scores schema comment corrected to
  pre-upload; get_most_redundant_mapped_file() added
- winnow/frigate_api.py: recognize_face returns (face_name, score)|None tuple
  so wrong-person scores never drive replacement or ceiling decisions
- winnow/config.py: FRIGATE_SCORE_THRESHOLD renamed to FRIGATE_SCORE_CEILING;
  ENABLE_FRIGATE_SCORES added
- tests/test_upload_tracker.py: 4 new tests for get_most_redundant_mapped_file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 18:35:11 +00:00
co-authored by Claude Sonnet 4.6
parent ed045f07dd
commit 6fcea587ff
9 changed files with 213 additions and 219 deletions
+2 -2
View File
@@ -31,7 +31,7 @@ class _Config:
MIN_CONFIDENCE: float = 0.7
MAX_AUTO_IMAGES: int = 80
QUALITY_REPLACEMENT: bool = True
FRIGATE_SCORE_THRESHOLD: float = 0.0
FRIGATE_SCORE_CEILING: float = 0.0
ENABLE_FRIGATE_SCORES: bool = True
# People filtering
@@ -64,7 +64,7 @@ class _Config:
self.MIN_CONFIDENCE = float(os.getenv("MIN_CONFIDENCE", "0.7"))
self.MAX_AUTO_IMAGES = int(os.getenv("MAX_AUTO_IMAGES", "80"))
self.QUALITY_REPLACEMENT = os.getenv("QUALITY_REPLACEMENT", "true").lower() in ("true", "1", "yes")
self.FRIGATE_SCORE_THRESHOLD = float(os.getenv("FRIGATE_SCORE_THRESHOLD", "0.0"))
self.FRIGATE_SCORE_CEILING = float(os.getenv("FRIGATE_SCORE_CEILING", "0.0"))
self.ENABLE_FRIGATE_SCORES = os.getenv("ENABLE_FRIGATE_SCORES", "true").lower() in ("true", "1", "yes")
self.FACE_MARGIN = float(os.getenv("FACE_MARGIN", "0.15"))
self.USE_FULL_RESOLUTION = os.getenv("USE_FULL_RESOLUTION", "true").lower() in ("true", "1", "yes")