diff --git a/docs/SPEC.md b/docs/SPEC.md index 1ab5a20..31b7efd 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -110,8 +110,19 @@ Two consequences worth stating: depends on timing. The same command run twice can produce different dumps, and a golden fixture cannot be built on that. -**Gap:** entire requirement, and it is **cross-repo** — the drop-versus-block -decision lives in KPN. Removing `max_faces` (AR-003) remains gated on it. +**Current:** fixed in KPN — node data outputs use `push_blocking`, sentinels +remain out-of-band so EOF can always overtake a stalled data path. Verified on +the same clip: 385 of 385 sampled frames written, zero drops, and two +consecutive runs byte-identical where previously they were not. + +It also ran *faster* (29 s → 17 s). A dropped frame has already cost its decode, +and the overflow exception cost more — so the lossy path was paying for work it +then discarded. + +**Gap:** the remaining half — bounding by **bytes in flight** rather than item +count. Channel capacity is still a count of items, and a face carries a 112×112 +crop plus a 512-float embedding, so a crowded frame occupies far more memory per +slot than a sparse one. That matters once `max_faces` is removed (AR-003). ## AR-005 — Face alignment and crop diff --git a/docs/requirements.md b/docs/requirements.md index cbae3d6..44d3efd 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -31,7 +31,7 @@ Status: `Done` · `In Progress` · `Planned` · `TBD` · `Withdrawn` | AR-001 | Detect faces in sampled frames; emit bbox, confidence, 5-point landmarks in original pixel space | SR-002 | High | Done | | AR-002 | Minimum face size **32×32 px** (VR-005 measured), expressed in **original** resolution (decoupled from `dense_scale`) | SR-002 | High | Planned | | AR-003 | No fixed per-frame face cap — crowd scenes must not lose background cast | SR-002 | Medium | Planned | -| AR-004 | Backpressure: unbounded faces/frame absorbed by slowing, never by dropping or throwing | SR-002 | High | **Blocked — cross-repo.** Every KPN node output uses the dropping `push()`; `push_blocking()` exists but is never called. Needs a KPN change | +| AR-004 | Backpressure: unbounded faces/frame absorbed by slowing, never by dropping or throwing | SR-002 | High | **Done** — KPN node outputs use `push_blocking`; sentinels stay out-of-band. Verified: 385/385 frames, 0 drops, byte-identical across runs | | AR-005 | Align to 112×112 via ArcFace 5-point similarity transform | SR-002 | High | Done | | AR-006 | 512-d L2-normalised embeddings, batched | SR-002 | High | Done | | AR-007 | Associate detections by IoU + embedding, with **frame-dependent** weighting | SR-002 | High | **Done** — `track_alpha` is the base for ordinary frames; drops to embedding-only on cut/boundary and for dormant tracks | diff --git a/external/KPN b/external/KPN index 4b6e498..be6e922 160000 --- a/external/KPN +++ b/external/KPN @@ -1 +1 @@ -Subproject commit 4b6e498ba7e70a34cc0b57638f9e56a43b7f41ae +Subproject commit be6e92268c2e9c7684d9247de851c02bb62334bd