Turn approved content opportunities (TASK-257) into YouTube playlists (topic/conference/era groupings) and Shorts (cut from approved quote timestamps, uploaded via TASK-249). Outward-facing: dry-run and explicit human approval before anything publishes; published items link back into _data for site rendering.
youtube.force-ssl; Shorts upload via youtube.upload (reuses TASK-249). All through bin/lib/youtube_client.rb (245).playlist: field already on _data/video_assets.yml platform entries (e.g. “RailsConf 2014 Interviews”, “GOTO Conference 2014 Interviews”, “WindyCityRails 2011 Interviews”) — a ready-made conference/era grouping to seed from; plus (b) approved topic/era groupings from TASK-257’s content-opportunity backlog.playlists.list (find existing by title) → playlists.insert if absent → playlistItems.insert for members not already present (dedupe by videoId within the playlist).videos.insert of a short vertical clip (≤60s, 9:16, #Shorts in title/description); YouTube auto-classifies it. There is no Shorts endpoint. So the only NEW work here vs 249 is a pre-upload ffmpeg clip-extraction step: cut the source master at the approved quote start/end (from TASK-257 approved quote timestamps) → vertical crop/pad → hand the clip to the TASK-249 upload pipeline unchanged (resumable, default private/unlisted, id written back).playlists.insert 50 · playlistItems.insert 50 each · playlists.list 1. videos.insert (each Short) 1600 — same ~6/day ceiling as 249, batch across days. A dozen playlists + their items ≈ low hundreds of units.playlist:/platforms[youtube].asset_id links (and Short asset_ids from 249) back into _data/video_assets.yml so the Jekyll archive can render the groupings/Shorts. Structure-only, per the primary directive.Reads: TASK-257 output, _data/video_assets.yml (playlist: field). Writes: _data/video_assets.yml (playlist ids + Short asset_ids). Uses bin/lib/youtube_client.rb (245) + TASK-249 upload pipeline + ffmpeg.