fix(upload): restore semaphore-based local file uploads
- Separate local file upload path from S3 queue-based producer-consumer
- Local files now use asyncio.gather with Semaphore (pre-S3 implementation)
- Fixes QueueFull crash when uploading more than 10 local files
- S3 uploads continue to use the bounded queue pattern
- cleanup=True only for S3 buffer files, False for local files