fix(podcast): the first real script parsed to zero turns, and retried forever
deploy / test (push) Successful in 5m28s
deploy / build (push) Successful in 5m53s

The baseline run the plan called for found a different defect than the one
it was written to find, which is the point of running it.

The worker was healthy: it found mission 01a0c9c4, found script.md in the
checkout — no reaper race — and parse_script returned ZERO turns, so it
skipped. Every two minutes. Forever. No episode, no tombstone, and the
same log line repeating, so nothing downstream could tell "not rendered
yet" from "never will be".

Cause: the skill asks the writer for `HOST:` and the writer, producing a
markdown file, wrote `**HOST:**`. split_once(':') then yields `**HOST`,
the `*` fails the all-uppercase test, every line falls to the
continuation branch with no turn to attach to, and the entire episode
parses to nothing. The skill is a prompt and models vary; the parser is
deterministic, so the parser is the half that gives. strip_emphasis
accepts `**HOST:**` and `_HOST_:` while leaving emphasis INSIDE a
sentence alone — that belongs to what is said — and a bolded non-speaker
line like `**Note:**` is still prose, not a turn.

Second defect, same symptom: "no spoken turns" now records a tombstone
(`unrenderable:no-turns`) instead of retrying a script that cannot
change. Every tombstone value keeps the `unrenderable` prefix so existing
readers still see one, and the suffix names which dead end it was — a
missing script and an unparseable one are different bugs and were
previously indistinguishable.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
This commit is contained in:
Omar Sobh
2026-09-22 11:01:21 -05:00
co-authored by Claude Opus 5
parent c1df958a13
commit ad6ce261d5
2 changed files with 92 additions and 10 deletions
+1
View File
@@ -1594,6 +1594,7 @@ print("ok")' >/dev/null 2>&1 \
from podcast_episodes where mission_id='$mission';\"" | head -1 | tr -d '\r')
case "$ep" in
'') fail "cr: no podcast_episodes row — the render sweep never reached this mission" ;;
unrenderable:no-turns*) fail "cr: the script parsed to zero spoken turns — the writer's format and parse_script disagree" ;;
unrenderable*) fail "cr: the episode is a tombstone (unrenderable) — the script was not found in the checkout OR the vault" ;;
*' 0') fail "cr: an episode was recorded with zero duration: $ep" ;;
*) pass "cr: audio rendered by $ep" ;;