Fix local CV visual-analysis client (HTTP/1.1) to enable YOLO selection

The local-cv provider was never exercised end to end (its bootstrap was
prohibited), and hid a latent bug: the JDK HttpClient defaulted to HTTP/2 and
negotiated an h2c cleartext upgrade that the HTTP/1.1-only worker (uvicorn/h11)
mishandled by dropping the request body, so every call returned HTTP 422. Pin the
client to HTTP/1.1.

With this fix the resident YOLOv8 worker (run offline against the existing
yolov8n.pt, no bootstrap script) classifies the sample source as CAR_VLOG at 0.95
with measured OpenCV blur/exposure and a real car label, replacing the previous
filename-keyword GENERIC_VLOG fallback. Provider remains opt-in via runtime
override; the committed localpoc profile keeps the heuristic default.

Also ignore yolov*.pt.license.txt (provenance for the git-ignored weights).
mvn -o verify green (247 tests, 0 failures).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bg76sLc43Wc3j5ZcLkboYR
This commit is contained in:
JSLMPR 2026-07-22 11:14:48 +02:00
parent 9d217c249e
commit 56205d91f2
3 changed files with 21 additions and 3 deletions

1
.gitignore vendored
View File

@ -46,3 +46,4 @@ yolov*.pt
# Local model bundle for the cinematic highlight PoC (large, provisioned out-of-band) # Local model bundle for the cinematic highlight PoC (large, provisioned out-of-band)
/models/ /models/
.claude/settings.local.json .claude/settings.local.json
yolov*.pt.license.txt

View File

@ -83,7 +83,15 @@ Ranked from the first render's evidence:
h1, 0.2 dB over — tightened to 0.72 for inter-sample margin.) Test added. h1, 0.2 dB over — tightened to 0.72 for inter-sample margin.) Test added.
- [x] P3.3 Overlay styling: refined 48px caption, soft drop shadow, thin subtle border, smooth alpha - [x] P3.3 Overlay styling: refined 48px caption, soft drop shadow, thin subtle border, smooth alpha
fade in/out (0.4s ramps). Verified rendering; committed 24bd1d7. (Placement/safe-area unchanged.) fade in/out (0.4s ramps). Verified rendering; committed 24bd1d7. (Placement/safe-area unchanged.)
- [ ] P3.4 Real CV visual analysis (resident model, no bootstrap script) to improve candidate selection. - [x] P3.4 **Real CV visual analysis via YOLOv8** (resident model, NO bootstrap script). Deps installed into
an isolated `.venv-local-cv`; uvicorn worker run directly against the existing `yolov8n.pt` offline
(`YOLO_OFFLINE=True`, telemetry sync off). Fixed a latent bug: the Java CV client negotiated HTTP/2
(h2c) which the HTTP/1.1-only worker mishandled (422/empty body) — pinned HTTP/1.1. Result on the DJI
source: category GENERIC_VLOG@0.25 -> **CAR_VLOG@0.95** (real `car` detection), measured blur 0.191 /
exposure 0.95 (OpenCV), method local_cv_worker_opencv_yolo. Provider stays OPT-IN via runtime override
(committed localpoc profile keeps the safe heuristic default; worker started manually).
CAVEATS: yolov8n.pt is **AGPL-3.0** (production blocker on this license alone; see yolov8n.pt.license.txt);
loopback HTTP is flagged non-compliant for a certified path; Haar face detector gives false positives.
- [ ] P3.5 Music/SFX creative fit + ducking review; consider longer inference / better prompts. - [ ] P3.5 Music/SFX creative fit + ducking review; consider longer inference / better prompts.
- [ ] P3.6 Freeze acceptance thresholds + blinded human creative review vs baseline before declaring success. - [ ] P3.6 Freeze acceptance thresholds + blinded human creative review vs baseline before declaring success.
@ -104,7 +112,11 @@ Ranked from the first render's evidence:
1080p/27.3s; mvn verify 246/0/0/0. 1080p/27.3s; mvn verify 246/0/0/0.
- 2026-07-22: **Beat-specific grading done & verified** (a0b6023). Grade varies per story beat; final - 2026-07-22: **Beat-specific grading done & verified** (a0b6023). Grade varies per story beat; final
re-render TP -2.3/-2.5/-2.8 dBFS, I -16.3 LUFS, 1080p/27.3s; mvn verify 247/0/0/0. Phase 3 visual/audio re-render TP -2.3/-2.5/-2.8 dBFS, I -16.3 LUFS, 1080p/27.3s; mvn verify 247/0/0/0. Phase 3 visual/audio
craft items complete. Next: P3.4 real CV selection, P3.5 music/SFX fit, P3.6 frozen thresholds + review. craft items complete.
- 2026-07-22: **P3.4 real CV (YOLOv8) done & verified.** Offline worker vs existing yolov8n.pt (no bootstrap).
Fixed latent HTTP/2 client bug. DJI source now classifies CAR_VLOG@0.95 with measured blur/exposure and a
real `car` label (was GENERIC_VLOG@0.25/filename heuristic). mvn verify 247/0/0/0. AGPL + loopback caveats
recorded. Remaining: P3.5 music/SFX fit, P3.6 frozen thresholds + blinded review.
## Deferred (until output-quality gate passes) ## Deferred (until output-quality gate passes)
Production hardening: Spring Security/OIDC, PostgreSQL/Testcontainers, containers/K8s, CI/CD, distributed Production hardening: Spring Security/OIDC, PostgreSQL/Testcontainers, containers/K8s, CI/CD, distributed

View File

@ -143,7 +143,12 @@ public class LocalCvVisualAnalysisProvider implements VisualAnalysisProvider {
} }
private static class JdkHttpExecutor implements HttpExecutor { private static class JdkHttpExecutor implements HttpExecutor {
private final HttpClient httpClient = HttpClient.newHttpClient(); // Force HTTP/1.1: the default client negotiates HTTP/2 (h2c cleartext upgrade) for http://, which
// the HTTP/1.1-only local CV worker (uvicorn/h11) mishandles by dropping the request body,
// producing a 422. Pinning HTTP/1.1 makes the loopback call reliable.
private final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.build();
@Override @Override
public HttpResult execute(HttpCall call) throws IOException, InterruptedException { public HttpResult execute(HttpCall call) throws IOException, InterruptedException {