Skip to content

feat: transcript-grounded, on-brand metadata authoring (#43)#52

Merged
jdwit merged 1 commit into
mainfrom
feat/agentic-copy-authoring
Jun 30, 2026
Merged

feat: transcript-grounded, on-brand metadata authoring (#43)#52
jdwit merged 1 commit into
mainfrom
feat/agentic-copy-authoring

Conversation

@jdwit

@jdwit jdwit commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Implements Phase-1 of #43. Gives an agent the two raw materials it needs to author good metadata - the spoken content of a video and a per-channel house style - and lets the existing videos update path apply the result. The agent writes; the CLI supplies grounding and applies changes.

What's new

Transcript grounding (src/ytstudio/commands/videos.py)

  • ytstudio videos captions <id> [-o table|json] - list caption tracks (captions.list).
  • ytstudio videos transcript <id> [--lang xx] [-o text|json] - download a track as clean plain text (captions.download, tfmt=srt); -o json adds track metadata. Surfaces a clear message when a track exists but is not downloadable (restricted ASR) instead of failing opaquely.

Per-channel brand voice (src/ytstudio/config.py, src/ytstudio/commands/profile.py)

  • Stored at profiles/<name>/brand.md, owner-only (0o600 in the 0o700 profile dir).
  • ytstudio profile brand show | set --file <path> | edit (edit opens $EDITOR and seeds a template). --profile/-p defaults to the active profile.

Skill guidance (skills/ytstudio/SKILL.md)

  • New authoring section: brand show -> transcript -> videos show -> draft -> videos update dry-run -> --execute, with the rules that the transcript is the source of truth for claims, the brand file for tone, and the agent never fabricates.

No new OAuth scope (youtube.force-ssl is already requested). External ASR/STT and bulk authoring stay out of scope for later phases.

How it was built

Designed and reviewed with a multi-agent workflow: parallel readers mapped the relevant subsystems and synthesized a code-grounded plan, then an adversarial review pass (5 dimensions, each finding independently verified) ran over the diff. Six confirmed findings were all fixed before this PR:

  • SRT parsing is now block-based, so cue text that is itself numeric (a countdown, a year like "2026") is no longer mistaken for a sequence index and dropped.
  • Consecutive-duplicate collapsing is gated to ASR tracks; a legitimately repeated line in a human caption ("Run! Run!") is preserved.
  • Caption download distinguishes a restricted/ASR 403 from a quotaExceeded 403, so quota exhaustion reaches the real quota handler instead of telling the user to "pick another track".
  • Tightened tests so the standard-over-ASR preference and the post-editor re-chmod are actually exercised (they previously could pass even if the logic were removed).
  • Corrected the quota cost documented for caption list/download (~50 / ~200 units, not ~1).

Tests

tests/test_captions.py (new) covers captions list (table/json/empty), transcript text/json, language selection, standard-vs-ASR preference, numeric-cue preservation, ASR dedup vs human no-dedup, not-downloadable, and quota-not-misreported; srt_to_text has direct unit tests (multiline join, tag stripping, empty). tests/test_profile.py adds brand show/set/edit including the owner-only re-chmod. Full suite: 338 passed, ruff clean, bundled skill reference regenerated.

Phase-1 of agentic copy authoring: give an agent the raw materials to write
grounded, on-brand video metadata, and let the existing videos update path
apply it.

- videos captions <id>      list caption tracks (captions.list), table/json
- videos transcript <id>     download a track as clean plain text (captions.download,
                             tfmt=srt), --lang select, -o text|json; clear message
                             when a track exists but is not downloadable
- profile brand show/set/edit  per-channel brand voice at profiles/<name>/brand.md
                             (owner-only), $EDITOR for edit, --file for set
- SKILL.md authoring section: brand show -> transcript -> show -> draft ->
                             update dry-run -> execute, with the grounding rules

No new OAuth scope (youtube.force-ssl already requested). External ASR/STT and
bulk authoring stay out of scope for later phases.

SRT parsing is block-based so numeric-only cue text (countdowns, years) survives;
consecutive-duplicate collapsing is gated to ASR tracks so repeated lines in
human captions are preserved. Caption download distinguishes a restricted/ASR
403 from a quotaExceeded 403 so quota exhaustion is reported correctly.
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.57143% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.03%. Comparing base (a179e78) to head (1636bf5).

Files with missing lines Patch % Lines
src/ytstudio/commands/profile.py 97.50% 0 Missing and 1 partial ⚠️
src/ytstudio/commands/videos.py 98.88% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #52      +/-   ##
==========================================
+ Coverage   84.28%   85.03%   +0.75%     
==========================================
  Files          15       15              
  Lines        2520     2660     +140     
  Branches      372      393      +21     
==========================================
+ Hits         2124     2262     +138     
  Misses        264      264              
- Partials      132      134       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jdwit jdwit merged commit d8342b4 into main Jun 30, 2026
8 checks passed
@jdwit jdwit deleted the feat/agentic-copy-authoring branch June 30, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant