DEV Community

Cover image for Three spec failures the YouTube watchdog surfaced before the publish-night cron
MORINAGA
MORINAGA

Posted on

Three spec failures the YouTube watchdog surfaced before the publish-night cron

Between July 17 and July 22, three consecutive longform YouTube specs got quarantined at 23:40 UTC. Each one passed the morning generation step, landed in content/yt-longform-queue/, and then failed the quality gate when the publish cron fired at night. Five days with no longform video.

The fix wasn't a better spec template. It was adding a pre-audit step to the existing queue watchdog that already ran at 08:00 JST — now it runs node scripts/audit-youtube.mjs on every pending spec it finds, roughly 15 hours before the night publish window. When a spec would fail tonight, I know about it at breakfast.

Here are the three failure types it caught in the first 24 hours.

The 15-hour timing gap

The publish workflow runs at 23:40 UTC (08:40 JST). When it quarantines a spec, the slot is burned for the day and there's no time to regenerate before the content window closes. The GitHub Actions job summary appears in Slack, but nobody is watching at 08:40 JST having just woken up — the alert is technically there and practically invisible.

The watchdog already existed. It was checking whether the main branch queue had gone stale — catching the branch-drift pattern where Shorts scripts authored on Claude session branches never merged to main. The pre-audit addition was one more job step: find pending queue specs, run the same audit binary the publish-night gate runs, fail the watchdog job if anything fails.

Same audit code, different time. The publish-night gate stays unchanged and doesn't get any weaker. The morning run just gives the problem a name 15 hours earlier.

Failure one: missing required fields

All three quarantined specs had the same root cause. The longform quality gate requires sources[], verified_at, and quality.* fields. These fields were added to the gate after the analytics auto-tuner started generating more longform specs — but the spec template in the generation prompt didn't list them explicitly. The prompt said "follow the quality gate requirements" without naming the specific keys.

The result: the spec passed the shape check at generation time (the YAML template had the right top-level structure), then failed the semantic check at publish time when the gate validated the field values and found them absent.

audit-youtube.mjs errors on an empty sources array with an explicit message: sources[] must contain at least one entry with url and title. That's clear. What makes morning detection valuable here isn't better error messages — it's the 15-hour window to regenerate the spec with the correct fields, test it manually, and commit it before the night window opens.

The structural fix was adding a self-check command to the directive's LONGFORM section, so the generation routine runs node scripts/audit-youtube.mjs on the new spec before committing it. The morning pre-audit is still there as a second gate. The self-check is only as reliable as the prompt following it; the watchdog is reliable regardless.

Failure two: hype phrases from recycled framing

The audit script checks each spec's title, hook, and summary against a banned phrase list — hype superlatives, "no one is talking about", vague openers like "have you ever wondered", and similar patterns.

The generation prompt tells the model to avoid them. It doesn't always. When a spec regenerates after a previous attempt scored well on some metric, the model sometimes borrows phrasing from that prior attempt, including phrasing that passed the style check but contains a hype fragment that the stricter audit catches.

One specific case from the first 24 hours: a spec title contained "the best open-source". That phrase is on the banned list. It would have failed at 23:40 UTC. The morning run flagged it at 08:00 JST, the job turned red, and I could fix the title in two minutes before starting anything else.

I haven't automated the fix — editing the spec file automatically introduces risk that a bad edit propagates silently. The watchdog flags it and stops. Manual edit, re-run audit, commit. The manual step is faster than debugging a bad auto-edit.

Failure three: Jaccard similarity to recent uploads

The audit compares each pending spec's title and hook against the last 30 uploaded specs using Jaccard token overlap. If the overlap exceeds 0.4, the spec is flagged as a likely duplicate — same framing, different surface text.

This fires most often after the auto-tuner keeps a winning archetype for four consecutive uploads. When the same archetype produces similar topics — say, three consecutive "game X has 10x more Y than game Z" style Shorts — the titles start sharing enough tokens that the fourth or fifth gets flagged.

Catching this at 23:40 UTC leaves no time to assess. The slot burns. Catching it at 08:00 JST means I can look at the pending spec and the uploaded history, decide whether the overlap is a real duplicate (same hook, same structure) or just a shared keyword cluster from the topic domain (two game comparison specs will both use "Steam" and "library" and "reviews"), and either let it through manually or regenerate with a fresh angle.

The Jaccard check isn't always right. A new Steam analytics spec and last week's Steam analytics spec will have high overlap. That's not a duplicate; it's the same subject area. The morning window is what makes the check useful — without it, a false positive costs a day's upload slot with no recovery path.


The change is one workflow step, 15 lines of shell added to an existing job. The audit binary was already there. The scheduling was already there. The only new thing is running the same check earlier.

What's changed: spec failures turn the watchdog red in the morning GitHub Actions summary instead of silently burning the night publish slot. Three failures in five days dropped to zero in the first week after the change.

Part of an ongoing 6-month experiment running three AI-curated directory sites. The technical claims here are real; this article was AI-assisted.

Top comments (0)