analytics-feedback
Turns channel analytics into pipeline behavior. YouTube Studio → Analytics → Content → Export → unzips to ~/Downloads/Content <range> <channel>/ with Table data.csv (per-video views, watch hours, CTR). This skill reads that export and re-derives which topics to chase and which to bury.
Usage
analytics-feedback.sh # newest export under ~/Downloads/Content*C0BALT_CUT*/
analytics-feedback.sh "/path/Table data.csv" # explicit file
analytics-feedback.sh --force # re-learn even if the export's mtime is unchanged
Idempotent: records the consumed export's mtime in work/_autopilot/analytics.csv.mtime and no-ops on an unchanged export (so it's safe to call every autopilot tick). Drop a fresh export into ~/Downloads and the next tick relearns.
What it writes
.claude/skills/schedule-drip/topics.scorelist— preserves everything ABOVE the# ==== AUTO (analytics-feedback) ...sentinel (your hand-curated rules are never touched) and regenerates the block below it with data-derivedGO <pattern>/HOLD <pattern>lines. Evidence (n=,med=,ctr=) is on#comment lines — never inline on a rule line, becauseschedule.pytreats everything after the verdict as the regex..claude/skills/scout-sources/niches.txt— preserves your manual seed queries and appends a regenerated AUTO block of search queries built from the GO winners (e.g. a winningblack[ -]?hole→black hole physics explained), so scout expands into proven niches. Additive only.work/_autopilot/topic_scores.json— full per-token evidence (n, median/mean/min/max views, mean CTR, median retention, total watch hours, verdict, suppressed-alias flag, manual conflicts). The audit trail.
Classification (env-tunable)
Per token (known entities from a lexicon + auto-discovered title tokens, deduped so #blackhole doesn't double-count black[ -]?hole):
- GO when
n ≥ AF_GO_MIN_N(3) ANDmedian_views ≥ AF_GO_VIEWS(600) ANDmean_ctr ≥ AF_GO_CTR(5%). Median + the n≥3 floor reject a single viral fluke (a 2-video token with one 6-view dud can't earn GO). - HOLD when
n ≥ AF_HOLD_MIN_N(2) ANDmedian_views ≤ AF_HOLD_VIEWS(60). Dead-is-dead needs less evidence than proven-winner. - neutral otherwise (no line emitted;
schedule.pydefaults unmatched sources to HOLD anyway).
A HOLD always wins over a GO in schedule.py, so the data can demote a manual GO (surfaced as a conflict in the JSON) but a manual HOLD veto still sticks.
Where it runs
- autopilot tick — first step of
autopilot.sh, before scout, so discovery + staging always reflect the latest export. - standalone — run it by hand after any fresh export to retune immediately.