Promotes the download-bound GPU-agent rewrite (milestone 122) + the detector fusion fix to main so the agent image (:latest) builds.
What
worker.py — producer/consumer pipeline. The workload is download-bound (download 400–5462ms vs GPU ~300–600ms), so the old N-slot serial chain idled the GPU during every download. New shape: downloader pool → bounded buffer(12) → 1–2 GPU consumers. Autoscaler scales downloaders by buffer occupancy (empty→add downloader; full→add a 2nd consumer if the GPU has util/VRAM headroom and it lifts j/s, else trim). Heartbeat thread keeps buffered leases alive past curator's 180s TTL; Stop drains both pools and releases every held lease at once. Consumers share one embedder/proposers instance (2nd consumer = concurrent inference, not N× VRAM).
Preserved resilience: lease exp-backoff, submit-path retry (#169), release-on-stop, region caps + video early-exit (#171).
detectors.py — fixes the 'Conv' object has no attribute 'bn' crash that silently disabled the yolo11n + comic-panel proposers on every image (ultralytics load-time Conv+BN fusion on a version-mismatched graph): disable that fusion + permanently self-disable a proposer on first inference failure instead of re-throwing per image.
app.py — UI reworked for the pipeline (tiles: downloaders · buffer · on-GPU · processed · errors + buffer-occupancy meter + consumers/waited-out line; dial tunes downloaders). Build marker 2026-07-01.1.
Verification
CI green on dev (run 1806: lint incl. ruff agent/ + agent compileall, backend, frontend, integration). CI has no GPU, so the pipeline itself is validated on the desktop after pull: throughput vs the ~3.85 j/s ceiling, GPU util steadier, buffer neither chronically empty nor full, Stop drains promptly, 'Conv' warning gone.
Promotes the download-bound GPU-agent rewrite (milestone 122) + the detector fusion fix to main so the agent image (`:latest`) builds.
## What
- **worker.py — producer/consumer pipeline.** The workload is download-bound (download 400–5462ms vs GPU ~300–600ms), so the old N-slot serial chain idled the GPU during every download. New shape: downloader pool → bounded buffer(12) → 1–2 GPU consumers. Autoscaler scales **downloaders by buffer occupancy** (empty→add downloader; full→add a 2nd consumer if the GPU has util/VRAM headroom and it lifts j/s, else trim). Heartbeat thread keeps buffered leases alive past curator's 180s TTL; Stop drains both pools and releases every held lease at once. Consumers share one embedder/proposers instance (2nd consumer = concurrent inference, not N× VRAM).
- **Preserved resilience:** lease exp-backoff, submit-path retry (#169), release-on-stop, region caps + video early-exit (#171).
- **detectors.py — fixes the `'Conv' object has no attribute 'bn'` crash** that silently disabled the yolo11n + comic-panel proposers on every image (ultralytics load-time Conv+BN fusion on a version-mismatched graph): disable that fusion + permanently self-disable a proposer on first inference failure instead of re-throwing per image.
- **app.py — UI reworked** for the pipeline (tiles: downloaders · buffer · on-GPU · processed · errors + buffer-occupancy meter + consumers/waited-out line; dial tunes downloaders). Build marker `2026-07-01.1`.
## Verification
CI green on dev (run 1806: lint incl. ruff `agent/` + agent compileall, backend, frontend, integration). CI has **no GPU**, so the pipeline itself is validated on the desktop after pull: throughput vs the ~3.85 j/s ceiling, GPU util steadier, buffer neither chronically empty nor full, Stop drains promptly, `'Conv'` warning gone.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The agent workload is download-bound (download 400–5462ms vs GPU ~300–600ms),
so the old N-slot serial chain (each slot: lease→download→decode→GPU→submit)
left the fast GPU idle during every download. Rearchitect worker.py into a
producer/consumer pipeline:
downloader pool (autoscaled by BUFFER OCCUPANCY) → bounded queue → 1–2 GPU
consumers (detect+embed→submit)
- Downloaders are I/O-bound → many overlap; the autoscaler now tunes DOWNLOADER
count by buffer fill (empty = GPU starving → add; full = outpacing GPU → add a
2nd consumer if it has util/VRAM headroom and lifts throughput, else trim).
- Bounded buffer (12) = backpressure: a full buffer blocks downloaders, capping
RAM + lease look-ahead. VRAM pressure sheds a consumer immediately.
- Heartbeat thread keeps every held lease alive (buffered jobs wait on the GPU;
curator's 180s TTL would otherwise reclaim them mid-buffer).
- Preserves all resilience: lease exp-backoff, submit-path retry (#169),
release-on-stop, region caps + video early-exit (#171). Stop drains BOTH pools
and releases every held lease at once (single held-set as source of truth).
- Consumers SHARE one embedder + proposers instance (a 2nd consumer adds
concurrent inference, not N× VRAM — bounds the VRAM creep seen with N slots).
- UI reworked for the pipeline: tiles show downloaders · buffer · on-GPU ·
processed · errors, a buffer-occupancy meter, and a consumers/waited-out line;
the dial now tunes downloaders. Build marker 2026-07-01.1.
Also fix the operator-flagged detector warning: yolo11n + the comic-panel model
threw "'Conv' object has no attribute 'bn'" on every image (ultralytics' load-
time Conv+BN fusion on a version-mismatched graph), silently disabling 2 of 3
crop proposers and spamming the log per image. Disable that fusion (unfused
inference is correct, marginally slower) and permanently self-disable a proposer
on the first inference failure instead of re-throwing forever.
Refs milestone 122.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Promotes the download-bound GPU-agent rewrite (milestone 122) + the detector fusion fix to main so the agent image (
:latest) builds.What
'Conv' object has no attribute 'bn'crash that silently disabled the yolo11n + comic-panel proposers on every image (ultralytics load-time Conv+BN fusion on a version-mismatched graph): disable that fusion + permanently self-disable a proposer on first inference failure instead of re-throwing per image.2026-07-01.1.Verification
CI green on dev (run 1806: lint incl. ruff
agent/+ agent compileall, backend, frontend, integration). CI has no GPU, so the pipeline itself is validated on the desktop after pull: throughput vs the ~3.85 j/s ceiling, GPU util steadier, buffer neither chronically empty nor full, Stop drains promptly,'Conv'warning gone.🤖 Generated with Claude Code