fix: address 4 code review findings (round 6)

- executor: snapshot has_frigate_model = effective_count > 0 before the
  upload loop; use it in the recognize_face gate instead of the live
  effective_count, which is incremented mid-loop and would otherwise
  trigger recognize_face calls against an empty Frigate model on first run
- jobs: restore if already_uploaded > 0 guard before limit = capacity so
  first-run auto-strategy jobs keep limit="auto" and the FPS adaptive
  early-stop can fire instead of always filling MAX_AUTO_IMAGES slots
- cli: retry get_people() once after a post-merge empty response before
  falling back to the pre-merge list; improve warning to name expired API
  key as a possible cause alongside transient network errors
- diversity: hoist hard_weight = np.where(...) above the FPS while loop
  since conf_array is constant; eliminates one O(n) numpy pass per
  selected image
This commit is contained in:
2026-06-16 22:22:51 +00:00
parent 2cb126a589
commit 692d77ee9f
4 changed files with 24 additions and 11 deletions
+7 -2
View File
@@ -363,6 +363,11 @@ def upload_to_frigate(jobs: list[dict]) -> None:
progress.console.print(
f" [dim]{name}: first run — Frigate diversity scoring will apply from the next run[/dim]"
)
# Snapshot whether Frigate has a model before the upload loop starts.
# effective_count is incremented inside the loop on each successful upload,
# so using the live value would incorrectly trigger recognize_face calls
# mid-batch on the first run (after the first upload sets it to 1).
has_frigate_model = effective_count > 0
actually_uploaded: list[tuple[str, str | None]] = []
failed_deletes: set[str] = set()
min_quality_score_for_slot: float | None = None
@@ -392,7 +397,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
# Pre-upload Frigate score — clean measurement (image not yet in training set).
# Called for all below-cap uploads (seeds frigate_scores for future at-cap
# replacement) and for at-cap uploads when scores already exist. Skipped on
# skipped when effective_count == 0 since Frigate has no model yet.
# skipped when has_frigate_model is False (effective_count was 0 before the loop).
# recognize_face returns (face_name, score); we only use the score when the
# best match is for the correct person. Mismatches (or "unknown") are treated
# as None so a wrong-person score never drives a ceiling skip or replacement.
@@ -408,7 +413,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
# rebuild-complete signal, poll it between recognize calls during replacement
# sequences rather than accepting stale/None scores.
pre_fscore: float | None = None
if Config.ENABLE_FRIGATE_SCORES and effective_count > 0:
if Config.ENABLE_FRIGATE_SCORES and has_frigate_model:
if not at_cap or person_has_fscores:
_result = recognize_face(fpath)
if _result is not None and (_result[0] or "").casefold() == name.casefold():