episode.yaml: the timeline follows the script, the cast survives - #28
Merged
Conversation
episode.yaml carries two things with opposite requirements. `voices` is the cast sheet an author hand-tunes and must survive regeneration -- there is a test protecting that, and it is right. `timeline` is derived from the script and must follow it. Preserving the whole file protected both, so deleting a paragraph left its id in the timeline while script.json moved on. `assemble` reads the timeline, so it went on splicing in audio for a line the manuscript no longer had: after an editorial pass that cut twenty paragraphs, ten of seventeen chapters narrated prose the book had removed, and one was also missing two lines that were in the script. Nothing reported any of it -- the render succeeded, the durations looked plausible, and the voice-line manifest said zero stale because every surviving line did match its text. The tell was a count: 716 script lines against 734 voice files. Now a non-forced run merges -- the timeline is rewritten from the plan, an existing cast is kept, and a character the manuscript has introduced since the last run gets a default voice rather than none. --force still overwrites both. The file is only rewritten when something actually changed. The test that failed asserted the whole file was preserved, which is the assumption behind the bug rather than a guard against it. Replaced with three: the cast survives a non-forced run, the timeline follows the script, and --force overwrites the cast too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The audiobook was narrating text the book had cut
episode.yamlcarries two things with opposite requirements:voices— the cast sheet an author hand-tunes. Must survive regeneration. There is a test protecting that, and it is right.timeline— derived from the script. Must follow it.Preserving the whole file protected both. So when an editorial pass deleted twenty paragraphs,
script.jsonmoved on and the timeline did not — andassemblereads the timeline. Ten of Production's seventeen chapters went on splicing in audio for lines the manuscript no longer had, and chapter 11 was additionally missing two lines that were in the script.Nothing reported it. The render succeeded, the durations looked plausible, and the voice-line manifest said zero stale — correctly, because every surviving line did match its own text. The tell was a count that should have been an equality:
Chapter 9 was still narrating 19 seconds of prose the book had removed.
The fix
A non-forced run now merges rather than skipping: the timeline is rewritten from the plan, an existing cast is kept, and a character the manuscript has introduced since the last run gets a default voice rather than none.
--forcestill overwrites both, and the file is only rewritten when something actually changed.The failing test asserted the whole file was preserved — the assumption behind the bug, not a guard against it. Replaced with three that state the narrower, correct guarantee.
Verified
All four books re-assembled from corrected timelines, 19 orphaned voice files removed:
Production lost 3.6 minutes — the cut paragraphs, no longer read aloud.
Note
This is the third silent-staleness bug in this pipeline, after the voice-line cache and
write_projectskippingscript.json. All three had the same shape: a derived artifact treated as durable, no error raised, plausible output. Worth remembering that the manifest caught the first two and could not catch this one — it verifies line contents, and this was a defect in the line set.🤖 Generated with Claude Code