# Private YouTube upload + companion linking

Use this after the user approves a hash-bound AutoShorts/TrueTraceShorts upload package.

## Procedure

1. Re-verify the current review/package hashes before uploading:
   - actual MP4 SHA256 equals `video_sha256` in the package and review package;
   - canonical posting-pack SHA excludes generated fields (`posting_pack_sha256`, `approval_command`) and equals the approved hash;
   - approval command exactly matches candidate ID, version, video SHA, and posting-pack SHA.
2. Run the upload-only executor, preserving the package directory if the package lives under a candidate output folder instead of the default `data/youtube_upload_packages`:

```bash
AUTOSHORTS_YOUTUBE_PACKAGE_DIR='data/post_candidates/<slug>/<version>/youtube_private_upload_package' \
python3 -m autoshorts.cli.youtube_private_upload_execute <candidate_id> \
  --version <version> \
  --approval 'APPROVED_FOR_PRIVATE_YOUTUBE_UPLOAD <candidate_id> <version> <video_sha> <pack_sha>'
```

3. Confirm upload output/audit:
   - `privacyStatus=private`;
   - `uploadStatus=uploaded`;
   - OAuth scope is only `https://www.googleapis.com/auth/youtube.upload`;
   - endpoints called are upload-only (`videos.insert`, plus `thumbnails.set` only if an approved thumbnail was packaged);
   - `containsSyntheticMedia` and `selfDeclaredMadeForKids` match the package;
   - no publication was performed.
4. Capture and report:
   - YouTube Studio edit link;
   - YouTube video ID;
   - Shorts link (`https://www.youtube.com/shorts/<video_id>`);
   - audit JSON path.
5. Update the website companion page immediately after private upload:
   - create/update the website candidate JSON and generated red-flag Markdown page;
   - set `videoUrl` to the real Shorts link in both website candidate JSON and generated content Markdown, even while the video is still private, because this user manually switches the upload to public right away;
   - generate/update the real start-frame thumbnail from the uploaded MP4;
   - run the website production QA command, not only a build;
   - browser-check the new page and confirm the `Open on YouTube` button is visible;
   - commit and push the companion update if the website repo is under git.

## Pitfalls

- The upload executor defaults to `data/youtube_upload_packages`; candidate-local packages require `AUTOSHORTS_YOUTUBE_PACKAGE_DIR`, otherwise it reports `Package not found` even when the generated package is valid.
- If an older/simple hash-bound package is approved but does not match the full repo CLI schema, use the documented direct fallback rather than weakening gates: validate package approval text, privacy, actual MP4 SHA256, and exact upload-only OAuth scope, then call only `videos.insert` and write an audit JSON. Do not broaden scopes and do not attempt read/public/comment/analytics APIs.
- A private YouTube upload creates a Shorts URL immediately, but the user still needs manual Studio review and publishing. Do not say it is public.
- For this user's current workflow, website companion pages should still expose the uploaded Shorts URL immediately after private upload; the user manually changes visibility to public right away. Report clearly that the website link is live while YouTube visibility remains manual.
- After any subtitle-position correction or re-render, the hash and approval command change. Never reuse the old approval command after a visual-only change such as moving subtitles into a logo-safe zone.
