Skip to content

Add trend-engine: predictive multi-agent trend→clip→publish workflow - #1

Draft
kaustin923 wants to merge 38 commits into
mainfrom
claude/trending-video-clips-automation-qu4qv6
Draft

Add trend-engine: predictive multi-agent trend→clip→publish workflow#1
kaustin923 wants to merge 38 commits into
mainfrom
claude/trending-video-clips-automation-qu4qv6

Conversation

@kaustin923

@kaustin923 kaustin923 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

What this is

A self-contained multi-agent workflow (trend-engine/) that forecasts trends before they peak, sources footage under a defensible license, clips + captions it, routes it through a human approval gate on Telegram, publishes to multiple platforms, and monitors performance to learn from what converted. Isolated from the Next.js portfolio app in its own package.

The brain is Claude Fable 5 (with server-side refusal fallback to Opus 4.8), and it's injectable — so the whole pipeline runs end-to-end offline against a mock brain with no API key. npm test proves it (32 tests).

Pipeline

Trend Forecaster → Sourcing → Editor → Compliance Gate → Telegram approval → Publisher → Monitor
                                                                                            └── learning loop ──▶ back into the forecaster

Deterministic control flow (orchestrator.ts); Fable does the reasoning (forecasting, caption writing).

Predictive, not reactive

The forecaster fuses reactive signals (Reddit/Trends/YouTube/HN) with upcoming catalysts (scheduled events 2–8 weeks out), places each topic on its hype curve (emergingsaturated), and returns a lead time + concrete post window. It deliberately skips saturated topics — e.g. it refuses generic World Cup content once the tournament is underway, and instead surfaces what's on the horizon (meteor-shower peak, an upcoming showcase, a seasonal ramp). A test locks this behavior in.

Legal-first by design

Every source clip carries LicenseInfo. The Compliance Gate hard-blocks unknown provenance and routes everything non-original to a human. There is deliberately no "grab an arbitrary copyrighted video" path. Sourcing pulls real licensed stock (Pexels) + Creative-Commons/public-domain (Wikimedia, with per-file license extraction that fails closed to unknown).

Component status

Component State
Trend Forecaster Built out (live APIs + fixtures; skips saturated; lead-time + post window)
Sourcing Built out (real Pexels + Wikimedia w/ license extraction; original)
Editor Built out (real ffmpeg reframe/trim/caption/attribution)
Compliance Gate Built out
Telegram approval Built out (raw Bot API, no deps)
Publisher Built out (official YouTube/TikTok/IG/X clients; missing creds → skipped)
Monitor + learning Built out (metrics joined to forecast; feeds back into the forecaster)

DRY_RUN=true (default) mocks all sources and publishes nothing. Live-only stages (ffmpeg exec, official publish, generated-original render) are guarded so live mode can't silently ship a stub.

Verification

  • npm run typecheck — clean
  • npm test32 tests pass: forecasting, saturation-skip, ranking, compliance, sourcing license mapping, ffmpeg arg-building, publisher skip-on-missing-creds, learning aggregation, and the full end-to-end pipeline (all offline against a mock brain)
  • Self code-review completed; findings fixed (nullable schema that would 400 the core live call, cross-platform path, TikTok chunk cap, unbounded learning read)

Known follow-ups

  • One live smoke test needed to confirm the Fable structured-output + refusal-fallback beta combo (can't be exercised offline)
  • Generated-original render path (AI b-roll + TTS) is an intentional hard throw, not a stub — the next real build for fully-owned content

Try it

cd trend-engine && npm install && cp .env.example .env
npm run scout   # forecaster only
npm start       # full pipeline (mocked end-to-end in DRY_RUN)
npm test        # 32 tests, offline

🤖 Generated with Claude Code

https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa

claude added 5 commits July 19, 2026 11:21
Self-contained package under trend-engine/ implementing a multi-agent
pipeline built on the Claude Agent SDK (claude-opus-4-8):

  Trend Scout → Sourcing → Editor → Compliance Gate → Telegram approval
  → Publisher → Monitor

- Trend Scout (crown jewel) built out: pulls Reddit/Google Trends/YouTube/
  Hacker News signals and uses Claude to cluster + rank scored topics
  (momentum, longevity, saturation, opportunity). Live free APIs with
  DRY_RUN fixtures.
- Legal-first design: every source carries license metadata; the Compliance
  Gate hard-blocks unknown provenance and routes all non-original content to
  a human Telegram approval gate before publishing.
- Publisher/Editor/Monitor stubbed behind DRY_RUN with explicit throws so
  live mode can't silently ship a stub.
- Runs offline in DRY_RUN (default); typechecks clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
trend-engine is a self-contained package with its own tsconfig and tooling;
keep the portfolio's `npm run lint` from scanning it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
… e2e tests

Addresses two problems: the product was reactive (chasing already-saturated
trends), and nothing was actually verified.

- Brain is now Claude Fable 5 (with server-side refusal fallback to Opus 4.8),
  and injectable via an LLM interface so the whole pipeline runs end-to-end
  offline with a deterministic mock — no API key needed to test.
- Trend Scout → Trend Forecaster: fuses reactive signals with UPCOMING
  catalysts (scheduled events 2–8 weeks out), places each topic on its hype
  curve (emerging/rising/peaking/saturated/declining), and returns lead time +
  a concrete post window. It down-ranks and SKIPS saturated topics — e.g. it
  refuses to post generic World Cup content once the tournament is underway,
  and instead surfaces what's on the horizon.
- Added upcoming-catalysts source (web-search-backed live, fixtures in DRY_RUN).
- Added node:test e2e suite (7 tests, all green) exercising forecasting,
  saturation-skip, ranking, compliance, and the full publish pipeline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
… green

Integrated the output of four Fable subagents (each on disjoint files) onto the
verified forecasting core, fixed integration typing, wired the learning loop,
and re-verified the whole thing end-to-end.

- Editor: real ffmpeg rendering — pure buildFfmpegArgs() (unit-tested), 9:16/1:1
  /16:9 reframe, ≤30s trim, drawtext caption + attribution card, spawn (no shell),
  http(s) source download; DRY_RUN still logs-only.
- Sourcing: real Pexels (stock) + Wikimedia Commons (per-file license extraction
  via mapWikimediaLicense; BY-SA/NC/unclear fail closed to unknown and are
  dropped); best-licensed-first, unknown filtered at the boundary.
- Publisher: official API clients (YouTube Data v3 resumable, TikTok Content
  Posting, IG Graph Reels, X v2); missing creds → skipped (never blocks the run);
  never publishes without an approved decision.
- Monitor + learning: records outcomes.jsonl joined to the forecast; getLearning
  Summary() aggregates what converted and is now injected into the forecaster's
  prompt (loop closed). Deterministic mock metrics (no Math.random).
- Fixed a generic union-narrowing error in publishers/common.ts poll().
- README updated to reflect built-out status + the predictive/forecasting model.

Verification: `npm run typecheck` clean; `npm test` 32/32 pass (forecasting,
saturation-skip, ranking, compliance, ffmpeg args, sourcing license mapping,
publisher skip-on-missing-creds, learning aggregation, full e2e pipeline).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
Self-review of the branch surfaced 6 findings; fixed the actionable ones:

- trendScout: forecaster schema made `catalyst` nullable via a type-array,
  which is outside Anthropic's structured-output schema subset and would 400
  the core live call — switched to anyOf [string, null]. (Highest-impact; only
  reachable in live mode, so mocked tests didn't catch it.)
- config: dataDir derived a filesystem path via URL.pathname, which breaks on
  Windows (/C:/…) and percent-encodes spaces — use fileURLToPath.
- tiktok: 50 MB base chunk could push the remainder-absorbing final chunk over
  TikTok's 64 MB per-chunk cap for large files — use 32 MB so the final chunk
  is always < 64 MB.
- learning: getLearningSummary read the entire unbounded outcomes.jsonl on every
  forecast — bound to the most recent 500 records (recency is what we want).

Left documented (not code-fixed): the Fable structured+fallbacks beta combo
needs one live smoke test to confirm compatibility; the e2e test writes to the
package data/ dir (low-severity test hygiene, gitignored).

typecheck clean; 32/32 tests still pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
@kaustin923 kaustin923 changed the title Add trend-engine: multi-agent trend→clip→publish workflow Add trend-engine: predictive multi-agent trend→clip→publish workflow Jul 19, 2026
kaustin923 and others added 24 commits July 19, 2026 08:30
… publishers, scheduler daemon + learning loop

Iteration 1 (Fable-orchestrated, Codex gpt-5.6-sol xhigh builders):
- Editor: real ffmpeg pipeline — download w/ cache, 9:16 1080x1920 render,
  ffprobe verification, capability-gated caption/attribution burn + .ass sidecar
- Sourcing: live Pexels/Pixabay/NASA/Wikimedia providers with true per-file
  license resolution; human-review-bypass mock removed
- Publisher: official API adapters (YouTube resumable upload, Instagram Graph
  container flow, TikTok chunked FILE_UPLOAD) — every adapter throws on DRY_RUN
  and on missing env keys; attribution re-appended on human caption overrides
- Scheduler: multi-daily daemon w/ jitter, stale-lock handling, run-state
  persistence, dedupe window; Monitor writes metrics.jsonl fed back to Scout
- Adversarial review: 17 findings, 4 must-fix fixed (drawtext escaping,
  TikTok >64MB chunking, attribution drop, DRY_RUN enforcement at call sites)
- 41/41 tests green, typecheck clean, e2e DRY_RUN pipeline verified
- Add .env.example covering the full env surface

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ublisher, learning module, tests) ported next

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s from cross-line review

Reconciliation of the superseded session line (cc96096) into this architecture:
- New src/publish/x.ts — X v2 chunked media upload + tweet post, DRY_RUN throw,
  fail-loud env, attribution-preserving 280-char caption composition
- New src/learning.ts + TopicOutcome records (outcomes.jsonl): monitor now joins
  metrics to topic domains/stage/recommendation; ranked learning summary
  injected into the forecaster prompt; deterministic FNV-1a dry-run metrics
- Regressions caught by cross-line compare and fixed: approval gate restored
  inside publish() (defense-in-depth), caption burn-in actually wired into the
  render, Wikimedia license matching widened back to 4-field haystack with
  NC/ND/SA fail-closed, source downloads stream to disk instead of buffering
- Instagram switched to resumable direct upload — public clip hosting
  (PUBLIC_VIDEO_BASE_URL) no longer required
- TikTok returns real public post id; shared caption composer w/ hashtag
  normalization and per-platform caps; expectJson error contexts
- 57/59 tests pass (2 skipped), typecheck clean, e2e dry-run verified

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The merged reorg broke two things the suite depends on:

- detectCapabilities() threw "ffmpeg not found" when ffmpeg was absent, so the
  editor failed on every topic in DRY_RUN — breaking the "runs fully offline"
  contract and failing 3 pipeline tests. A capability *probe* must never throw:
  it now degrades to {drawtext:false, subtitles:false}. Live rendering still
  fails loudly at probe()/runFfmpeg() when ffmpeg is missing, so nothing real
  is silently skipped.
- Test files isolate by mutating the shared config.dataDir singleton, which
  races when Node runs files concurrently (intermittent scheduler-test failure).
  Serialized the filesystem-heavy suite with --test-concurrency=1.

Result: typecheck clean; 50/50 tests pass deterministically across repeated runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
…ls, launchd daemon

Iteration 2 (5 Codex gpt-5.6-sol xhigh builders, adversarial review, 7 must-fix resolved):
- Originals: macOS say TTS voiceover (temp-file input, injection-safe) + whisper.cpp
  word-timed captions (16kHz WAV transcode) with proportional fallback; draftOriginal
  assembles licensed b-roll + narration into license-type 'original' drafts with
  syntheticMedia flag; strict b-roll gate; 9:16 enforcement per platform
- AI disclosure propagates: YouTube containsSyntheticMedia, TikTok is_aigc
- Telegram: sendVideo preview cards, MarkdownV2 escaping (incl. backslash),
  persisted getUpdates offset, reject-with-reason, approvals.jsonl audit log,
  approval-gate now fails closed if the review card cannot be delivered
- Live analytics: real YouTube/TikTok/IG/X stats fetchers; failed fetches skip
  records instead of writing zeros (learning-poison guard)
- Leading signals: TheSportsDB calendar, Wikipedia pageview acceleration, GDELT
  news velocity, Google News RSS — keyless, fixture-backed, zero-fetch DRY_RUN
- Daemon: launchd install/uninstall scripts (single-run npm start per fire,
  run.lock prevents overlap); scheduler jitter clamp + conditional releaseLock
- 90/92 tests pass (2 env skips), typecheck clean, no-network dry-run verified

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kept iteration-2 ffmpeg.ts (lazy probe, textfile filter, audio duration probe);
applied their .catch() so the capability probe degrades instead of throwing
when ffmpeg is absent. Took --test-concurrency=1 for the fs-heavy suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nance receipts + operating rulebook

Iteration 3 (4 Codex gpt-5.6-sol xhigh builders, adversarial review, 1 must-fix resolved):
- Originals publish per run (ORIGINALS_PER_RUN, default 1): sourced + original
  paths share compliance/approval/publish/monitor; distinct dedupe keys;
  mockLlm narration branch; e2e asserts the original flows end-to-end
- Hardening: all 8 prior review findings fixed (Telegram caption/offset/cross-
  card decisions, zero-view guard on all platforms, plist XML+shell escaping,
  two-layer filter-filename escaping, strict audit toggle, IG token placement)
- Quota preflights: per-platform daily counters in state.json, IG publishing-
  limit + TikTok creator_info preflights, YouTube quota-unit ledger
- Provenance receipts: per-publish SHA-256 + license snapshot + approval
  linkage + post id → data/provenance.jsonl
- docs/RULEBOOK.md + rulebook.json: 5-agent research pass distilled into
  tiered green/yellow/red format rules, platform requirements, enforcement
  reality, monetization roadmap — compliance-gate encoding queued
- npm scripts load .env natively (node --env-file-if-exists)
- 120/120 tests green (full ffmpeg: caption burn-in tests now active),
  dry-run publishes 12/12 incl. the originals path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First live run hung indefinitely on a source fetch (0.7s CPU, blocked on I/O).
Promise.allSettled already isolates per-source failures, so a timed-out source
now simply drops from the round instead of stalling the whole run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mplate engine, source health + events calendar

Iteration 4 (4 Codex gpt-5.6-sol xhigh builders, adversarial review, 4 must-fix resolved):
- Compliance now assigns green/yellow/red tiers per docs/rulebook.json:
  red = hard block before approval (unknown license, unlicensed music,
  social-CDN sources, watermarked re-exports); yellow forces human review
  with rulebook condition checklists; music gate fails closed on missing
  audio provenance; editorial-stock flags survive the originals lane
- Telegram cards render tier + conditions; yellow drafts require an explicit
  YES reply (approve button alone won't publish); red never reaches a card;
  licensed-clip monthly budget gate (LICENSED_CLIP_BUDGET, default 0)
- Anti-template variation: per-video structure fingerprints, n-gram
  similarity check vs last 20, one vary-regeneration then yellow-flag;
  deterministic caption-style rotation — the inauthentic-content defense
- Source health per run (count/ms/error/timeout per source) + fixes from live
  diagnosis: Google Trends daily RSS was 404-dead → replaced with live
  trending RSS; Reddit 403-blocks our UA → explicit degraded status;
  Wikipedia derives watch terms from other sources; new keyless
  events-calendar source (near-term entertainment/cultural events)
- 151/151 tests, dry-run 12/12 publishes, scout prints source health

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…epair, corrective re-ask

First live pipeline run crashed on malformed JSON from the forecaster
(fallback-path output; parse error at char 4338). structured() now retries
once on truncation with doubled budget, repairs prose fringes and trailing
commas, and re-asks once with the exact parse error before failing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Second live run died on the SDK's 10-min default request timeout during the
xhigh forecast over 85 signals. Client now allows 20 min with 2 retries, and
structured/research calls log elapsed seconds so long phases are visible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ommand center

Iteration 5 (4 Codex gpt-5.6-sol xhigh builders, adversarial review, 2 must-fix resolved):
- npm run oauth:youtube — local consent flow mints YOUTUBE_REFRESH_TOKEN into
  .env (backup first, secrets never logged, state-validated, 5-min timeout)
- Policy-drift watcher: 24h sha256 checks of YouTube/TikTok/Meta/X monetization
  policy pages from the daemon; drift → data/policy-drift.jsonl + Telegram alert
- Claim-ops: data/claims.jsonl + CLI; takedown/strike auto-blacklists the
  rights holder; sourcing drops blacklisted matches on word boundaries only
  (review caught substring over-match nuking whole providers)
- Telegram command center: /status /health /pause /resume /run from the owner
  chat only, offset-coexistent with approval polling (cross-process collision
  fixed via review), scheduler honors pause + run-now with interruptible waits
- 186/186 tests, dry-run 12/12

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ox kits

Iteration 6 (2 Codex gpt-5.6-sol xhigh builders + campaign research, 1 must-fix resolved):
- GDELT gets its own 15s timeout + lighter query (5 terms, 3d timespan)
- renderToVertical: two-pass loudnorm to -14 LUFS, capability-gated,
  never fails the render; silent/no-audio inputs skipped cleanly
- Manual-post lane: approved drafts (and missing-credential publish rounds)
  write data/outbox/<date>-<topic>/ kits — MP4 + per-platform caption files +
  meta.json + AI-disclosure README; provenance gains outbox records
- Review catch: attribution could be tail-truncated out of kit captions —
  now reserved before body truncation (license credit survives any cap)
- 202/202 tests green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nual-era tracking, reports + experiments

Iteration 7 (4 Codex gpt-5.6-sol xhigh builds incl. one prerequisite-race rerun, 2 must-fix resolved):
- Forecast calibration: every live forecast persisted; opportunity-decile vs
  realized platform-normalized percentile; summary injected into the
  forecaster prompt (the scorer reads its own report card)
- Feature attribution: contentFeatures on every outcome (angle/hook/tier/
  voice/hour), exponential 21d-half-life decay, platform-percentile
  normalization, min-sample guards; duplicate-entry dedupe (latest wins)
- Manual-era tracking: npm run track register|views + Telegram /track;
  registered YouTube URLs auto-fetch public stats; manual metrics flow into
  the same outcomes pipeline — learning works from the first manual post
- npm run report + /report: calibration table, top/bottom features, platform
  performance, manual coverage, computed recommendations → eval-report.json
- Experiment scheduler: deterministic one-feature-at-a-time rotation into
  data/experiments.jsonl, surfaced as a soft hint to the editor
- 223/223 tests green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ELEVENLABS_API_KEY + ELEVENLABS_VOICE_ID in env → synthesis via the
text-to-speech API (60s timeout, key never logged), mp3→AAC via existing
ffmpeg helpers, whisper word-timing unchanged; any failure falls back to
say silently. audioProvenance records elevenlabs vs macos-say so provenance
and AI-disclosure stay accurate. 226/226 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- studio/ package (Remotion 4, deterministic headless renders, offline fonts,
  VideoToolbox encode): ticket/receipt design system, split-flap type, animated
  charts, word-synced karaoke captions from whisper timestamps
- Demo episode (concept proof) + Episode 1 "Your Phone Learned to Listen
  Offline" — educational format: six-scene curriculum, phone-mockup diagrams,
  ElevenLabs VO (key read from trend-engine/.env at runtime, never logged)
- Review verdicts: demo "top-1% trajectory, not another template";
  episode 1 "Ship — educational identity fully realized, visuals teach"
- Known polish: ep1 section-03 card flight path clips a headline transiently

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two new tests in elevenlabs-tts.test.ts hard-failed in environments without
ffmpeg (the silentMp3 helper spawns it) or macOS `say` (the fallback path) —
unlike the rest of the suite, which skips such tests when the binary is absent.
Added the same `t.skip(...)`-on-missing-binary guard used by
editor-ffmpeg-render.test.ts, so the suite is green on Linux/CI too.

typecheck clean; 214 pass / 0 fail / 12 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wUwQZt9XQTUApHoksqrFa
…, env binary paths, yuv420p limited range

Both compositions re-rendered and verified: -14.10/-14.09 LUFS, yuv420p
BT.709 TV range, previously-clipped frames confirmed clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Iteration 8 (3 Codex gpt-5.6-sol xhigh builders, 2 must-fix resolved):
- Pitch generator: 3-5 bold pitches per run with a hard quality bar
  (≤9-word curiosity headlines, cross-domain angles, 'X explained' banned,
  vertical diversity), owner feedback history feeds future generations
- Telegram pitch cards: natural-language replies ('1 yes, 2 no, 3 yes but…')
  parsed per-pitch, feedback captured to the taste loop, owner-chat-locked,
  offset-coordinated with approval polling, 4h expiry
- Studio bridge: approved pitches → script agent → studio script.json →
  Remotion render with ElevenLabs VO → existing video approval card → outbox;
  STUDIO_MODE default on when studio/ exists, classic path preserved
- 240/240 tests, dry-run logs the full two-gate plan

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t-date verification

Studio: two-speaker dialogue (per-line ElevenLabs synthesis Jessica x George,
concat + -14 LUFS loudnorm, whisper word-timing), speaker-colored karaoke
captions with J/G chips, per-episode theme accent tokens (script.theme).
Rendered dialogue-test.mp4 verified: 2 voices, style-switching captions,
red accent, -14.2 LUFS, yuv420p.

trend-engine: event-date verification — forecaster drops past/undated catalysts
(past events → aftermath stage only), events-calendar recency filter, pitch
verification pass (LLM checks event hasn't happened before Telegram), cards show
explicit dates + days-away. Closes the wedding-pitch bug. 245/245 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…+ label-collision polish

Replaces the fake placeholder charts (hardcoded ONE/TWO/PACE bars + raw
stage-direction text dumped on screen) with a typed Viz union: title,
rangeBar, counter, statBig, compareBars, leaderboard, meter, grid, split —
each rendered from real numbers in the script. Fixed rangeBar label
collisions and counter double-minus. Spider-Man episode now renders verified
box-office data (Deadline $180-190M, Toy Story 5 $160M, AMC -$632M loss,
No Way Home $260M, $4.09B debt / $1.95 stock).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s from LLM schemas

Anthropic structured-output rejects array minItems/maxItems > 1 with a 400.
Both the pitcher (pitches 3-5) and studio-bridge (scenes 4-6) schemas set
these, so every live pitch-generation and script-generation call failed and
the daemon punted to the next day — no pitches ever reached Telegram. Counts
are already enforced in the prompts; dropped the schema constraints. Also
ANTHROPIC_EFFORT=low (forecast ~2min vs ~10min at high). 245/245 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… per-line concat

Fixes the choppy 'reading from a slide' delivery — the whole conversation is
synthesized in one /v1/text-to-dialogue request (eleven_v3) with prosody
carrying across turns, per-speaker voices, and native timestamps for caption
alignment. Conversational script + Eric voice (stability 0.65, less emotion).
Single-voice episode-1 path unchanged. NOTE: current cut runs ~100s — script
trim to ~50s pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kaustin923 and others added 9 commits July 19, 2026 19:06
…-mechanics pitches

Owner feedback: pitches lacked a visceral so-what. Rewrote the quality bar to
require personal, visceral stakes (viewer's money/time/what they watch), and
to reject corporate-mechanics headlines unless reframed around what the viewer
feels.
…rements

Owner direction: pivot hard to sports/fantasy football (booming audience),
every pitch must be non-obvious (kill anything a fan would call 'obviously')
and dead simple (one clear idea, no dense stat-chains — the AMC video was too
hard to follow). At least half of each batch sports/fantasy.
…rlap/empty cards + fantasy football episode

Fixes: long spoken lines no longer render as a giant headline colliding with
the viz; no-viz reaction lines render as a single clean centered statement
(not an empty card); bigger caption bar. New sports/fantasy episode
'The August Tell' (green gridiron theme, Tuten empty-job signal, ELI5).
New src/field/ system (FieldLayer w/ yard lines+hash marks, PlayerDot,
RouteArrow telestrator, FieldCard/Chip, geometry) + five shown-scene viz
kinds: fieldPlay (lane opens, runner bursts through), depthFlow (starter
fades, touches flow to riser), speedRace (40-yard strip race vs NFL avg),
zoneHeat, riseRank. Breakouts episode re-shot so every player's situation
passes the muted-viewer test — field diagrams instead of stat cards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt timing, silent track, proportional captions)
…ess — silent previews validated

Both scripts staged (narrator format, humanized-voice settings ready,
fact-checked numbers) and silent-rendered clean. Render-ready the moment
ElevenLabs credits are restored.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants