| name | schedule-drip |
| description | Deterministic greedy scheduler over the graded clips — the only skill that attacks the |
| allowed-tools | Bash |
| user-invocable | true |
schedule-drip
The selection suite's drip stage. The pipeline today is produce-only: it renders
clips and stops. The human picks ~19 by hand, dies 37% of the time on topic, and
the channel takes 7-day dark gaps while ~80 quality clips rot on disk. With no
evergreen tail (86-100% of a short's views land in days 1-3), a dark day is
permanent lost reach — the #1 unconfounded leak in the 28-day analytics.
schedule-drip is the deterministic greedy scheduler that fixes it. It consumes
grade-clip's grade.json verdicts plus a checked-in topic scorelist and stages
a daily drip into output/_toupload/<date>/. Staging-handoff only — it never
uploads (there is no API key in the stack); a human posts from the dated
folders.
Usage
schedule-drip.sh [output_dir=output]
Inputs
- Every
output/**/*.grade.json (skips _preview / source / _toupload /
_triage). The locked schema lives in SELECTION-SUITE-CONTRACT.md.
topics.scorelist (checked in here) — one rule per line, <GO|HOLD> <regex>,
matched case-insensitively against source-slug + title. HOLD is a denylist
and WINS over an incidental GO substring (e.g. "focus" inside a
productivity-death source's "stay-focused"). Default when nothing matches:
HOLD (conservative).
- OPTIONAL
output/upload-log.json — a list, or {uploaded|posted: [...]}, of
already-posted clip paths / basenames / titles. Absence means "nothing posted
yet" — never a crash.
- "Today" comes from the system
date.
Algorithm (deterministic greedy)
- Gate (GOLD-first): keep a clip only if
tier==GOLD with no hard_caps, OR
grade>=GRADE_MIN_UPLOAD with no hard_caps. A clip with any unfixed hard cap
stays out of the drip until fix-cold-open repairs it.
- Drop posted: anything matched in
upload-log.json.
- Rank by grade desc (then source, then path for stable ties).
- De-dupe near-identical: same source + ≥0.7 title-token overlap → keep the
higher grade, drop the rest (collapses the
clip / clip-1.25x speed-up twins).
- Topic verdict: GO vs HOLD from
topics.scorelist.
- Place GO first into the horizon, one day at a time,
POSTS_PER_DAY per day,
MAX_PER_SOURCE_PER_DAY round-robin across sources (the 53-from-one-source
feed-fatigue fix — no day ever gets two clips from the same source).
- Backfill dark days with HOLD clips only — a HOLD clip is never dripped ahead
of a GO clip, only into a day that would otherwise be dark.
gap_warnings — any day still empty after backfill (the dark-gap alarm).
Output
output/_toupload/<YYYY-MM-DD>/ per filled day: the staged clip (copy) +
metadata.txt (lowercased title + #-hashtags from the matched GO rule and the
source slug, plus #shorts #fyp).
output/_toupload/schedule.json — {generated, horizon_days, posts_per_day, max_per_source_per_day, days:{date→[clips]}, gap_warnings, backfilled, drops}.
drops records every not_schedulable / already_posted /
dedupe_near_identical / horizon_full decision.
Idempotent: _toupload is rmtree'd and rebuilt every run — a re-run yields a
byte-identical plan and never duplicates staging. Non-fatal: any error exits 0
without staging.
Knobs
| Env | Default | Meaning |
|---|
POSTS_PER_DAY | 1 | clips staged per day |
MAX_PER_SOURCE_PER_DAY | 1 | per-source round-robin cap (feed-fatigue fix) |
DRIP_HORIZON_DAYS | 14 | days to plan ahead |
GRADE_MIN_UPLOAD | 60 | shared with grade-clip; the schedulable grade floor |
Why new
There is no selection / scheduling step at all. This is the only skill that
directly attacks the dark gap and the backlog rot — it turns "101 produced / 19
uploaded" into a multi-week daily drip with zero new source ingestion.