v1.1.0 — first release
Changelog
All notable changes to Showrunner are documented here. Format follows Keep a Changelog; the project tracks loose semver — minor bumps for new capability, patch for fixes.
1.1.0 — 2026-05-23
First tagged release. Versioned 1.1.0 rather than 0.1.0 because the project has been tracked as "v1.1 — reliability hardening + provider-agnostic refactor" throughout development; this is the first cut where the pipeline works end-to-end against real Next.js targets and the LLM + TTS layers are swappable. No 1.0.0 was ever published.
Added
- Provider-agnostic LLM layer (
llm.default+ per-stagellm.overrides). Four providers:anthropic— Claude via the official SDK with structured outputs.openai—gpt-4o-style models viaresponse_format: json_schemawithjson_objectfallback.agent_bridge— spawn a headless CLI agent likeclaude -p --output-format json; no API key on file required. Supportsspawnandfile_pollmodes.custom— dynamic-import an operator-supplied module conforming to theLLMProviderinterface.
- Provider-agnostic TTS layer (
voiceover.provider). Three providers:elevenlabs— the only one that returns per-character alignment.openai—tts-1-hdvia the audio API.custom— dynamic-import for in-house TTS pipelines.
alignment_strategy: required | best_effort— when a TTS provider doesn't return alignment, switch automatically to per-segment synthesis (one TTS call per segment) so audio doesn't get sliced across mid-word boundaries.showrunner doctor— preflight checks before any run. Validates config syntax, provider env vars, ffmpeg + ffprobe on PATH, Playwright chromium binary, target URL reachability, free disk on every output dir, free memory + computed ffmpeg thread cap, and lifecycle script executability. Wired intorunimplicitly (escape with--skip-doctor).showrunner record-actionswith scroll capture. Drives a headed browser; captures click / input / change / keydown / submit / scroll events; coalesces them into a clean action stream. Scroll capture is 250 ms debounced with direction coalescing.- DOM preflight in the
scriptstage — scrapes the live target's actionable selector inventory (≈60–80 entries on a typical marketing site) before asking the LLM for a manifest. The LLM is constrained to inventory selectors only, with a one-shot remediation retry if it strays. - Resource preflight in
recordandmuxstages — checks free disk against estimated artifact sizes, computes an ffmpeg-threadscap from free RAM × resolution × quality preset (SHOWRUNNER_FFMPEG_THREADSenv override available). - Structured ffmpeg errors — categorized as
oom | no_space | codec_missing | permission | unknown, with per-category remediation hints. --resolutionflag on bothinitandrun. Presets:low(854×480),standard(720p, the default),high(1080p),extreme(4K). Onrunit overrides bothrecording.viewportandoutput.resolutionin one step so they stay matched and mux doesn't upscale.initflags:--llm-provider,--tts-provider,--resolution. Scaffolds ademo.yamlwith the right provider blocks, an.env.examplelisting only the env vars that combination actually needs (deduplicated when LLM + TTS both use OpenAI), and a realdocs/PRD.mdstub with section guides.- Legacy config auto-migration — pre-v0.1
demo.yamlfiles with flatvoiceover.{voice_id, model, ...}fields and nollmblock are normalized at load time. Existing configs keep working with zero edits. validate --strict— exit nonzero on missing provider env vars (otherwise warns).- Captions — SRT + VTT emitted alongside the final MP4 when
output.captions.enabledis set. Whole-segment cues are used as a fallback when per-character alignment isn't available.
Changed
engines.nodebumped to>=20.6(needed forprocess.loadEnvFile).initdefaults:script.vo_review_gate: false(was true),recording.viewport: 1280×720(was 1920×1080),output.resolution: 1280x720. Each is opt-in to the larger/stricter value via a one-line edit.tsupconfigured withskipNodeModulesBundle: trueandtarget: 'node20'. Builtdist/cli.jsdropped from 1.75 MB to 247 KB and no longer crashes withDynamic require of "tty" is not supported—npm linkandnpm i -gare viable now.- README rewritten for v0.1 — install path (with
npm link), full prereqs (Node ≥ 20.6, ffmpeg, chromium), provider-choice tables, pipeline-per-stage table, daily-commands cookbook, troubleshooting section.
Fixed
understand --interactiveno longer silently exits after the second question on piped stdin. Replacedreadline/promises.question()with a queued'line'-event reader that handles both TTY and pipe semantics.understand --output <path>now correctly takes precedence overproject.product_modelin the config (was silently overridden).- Script-stage prompt now bans Tailwind arbitrary-value class names (
.max-w-[1280px]) which aren't legal CSS and crashed Playwright with aSyntaxError. A post-validator catches violations and retries once with a remediation prompt before accepting the manifest. looksUnstable()heuristic now catches Next.js compiled-CSS classes like__variable_3eb911(leading underscores were previously slipping past).muxoutput write now falls back to a timestamped sibling MP4 when the canonical path is locked by a media player, with a warning, instead of failing the run.
Known limitations (Tier 3 — coded but not exercised end-to-end)
- OpenAI LLM + OpenAI TTS provider paths are wired but were not run with a real API key in v0.1 validation. The agent_bridge + ElevenLabs combination is the validated default.
agent_bridgefile_poll mode is coded but onlyspawnmode was exercised.- Custom provider modules (LLM + TTS) — dynamic-import loader is wired but no reference implementation has been swapped in.
instrument,capture-auth,trace,preview,rerun-segment,print-vo,approve-vocommands are mostly thin wrappers but were not stress-tested in v0.1.- Background music mix and title-card logo / custom-font rendering are coded but were not exercised.
- 1920×1080 mux remains RAM-sensitive on tight boxes; the thread-cap heuristic mitigates but the safe default is
--resolution standard.
Validation artifact
A real end-to-end run against the Credstone Atlas marketing site produced output/ct-website-atlas_demo.mp4 (4.3 MB, H.264 + AAC, 1280×720, 48.2 s, with SRT + VTT) using:
agent_bridgeLLM (via localclaudeCLI, no Anthropic key on file)- ElevenLabs TTS with
alignment_strategy: required - DOM preflight + selector validator producing inventory-only manifest selectors
- Full mux preflight + thread cap on a 5.9 GB RAM machine with 1.1 GB free at run time