The audit skill already generates youtube title/description/tags/chapters into _data/interviews.yml and _data/video_assets.yml. This task pushes that existing metadata to the live YouTube videos via the Data API — generation is out of scope here, this is sync only. Outward-facing: nothing goes live without an approved diff.
The task text says metadata lives in _data/interviews.yml + _data/video_assets.yml. Investigation shows it actually lives in _data/transcripts/*.yml under the youtube: block (title, description, tags, chapters). chapters exist ONLY there. Read from the transcripts, not from interviews/video_assets. (video_assets.yml per-platform description is stale platform copy, not the generated metadata.)
_data/transcripts/<stem>.yml with a youtube: block → transcript_id = <stem>._data/video_assets.yml item where transcript_id == <stem> → platforms[] where platform == youtube → asset_id (the live YouTube video id). Skip assets with no youtube platform.title → snippet.title; description + chapters → snippet.description; tags → snippet.tags.
chapters list as lines (00:00 Title) into the description text; first line must be 00:00, need ≥3 chapters, each ≥10s apart — validate and warn if the generated set violates this.videos.list(part=snippet, id=<asset_id>) = 1 unit each.videos.update(part=snippet) = 50 units each.youtube_metadata dry-run job: list live snippet, diff desired-vs-live (normalize whitespace/tag order), emit a per-video diff artifact + live-state fingerprint (hash of live title+description+tags). No writes.videos.update. Abort on drift._data. Skip any video whose live snippet already equals desired (no-op). Fingerprint-idempotent job key = asset_id + sha(desired_snippet).Reads: _data/transcripts/*.yml, _data/video_assets.yml. Uses bin/lib/youtube_client.rb (245). No repo writes.