# Starsend Studio — Consultation Synthesis
## Autonomous 30-Second Microseries Production Box

**Date:** 2026-03-02
**Rounds:** 3 (Claude + Gemini 3.1 Pro)
**Status:** Architecture locked. Cleared for PoC.

---

## 1. LOCKED ARCHITECTURAL DECISIONS

| # | Decision | Details | Source |
|---|----------|---------|--------|
| 1 | **Monorepo** | Add `starsend/studio/` to existing Starsend engine. Same SQLite DB with new `studio_cycles` and `studio_tasks` tables. Shared API clients, cost tracker, shot router. | R1 agreed, R2 locked |
| 2 | **Comment-based voting** | Abandon YouTube Community Post polls (API cannot read them). Use "Comment 1, 2, or 3" on all platforms. Two-pass counting: regex first, batch ambiguous to Haiku. YouTube is canonical vote source. | R1 kill risk, R2 locked |
| 3 | **Hybrid autonomy** | Dumb state machine orchestrator (hardcoded phase transitions). Smart LLM recovery agents inside modules only. Stateless for PoC — no self-modifying routing. If recovery fails 3x, escalate to JT via Telegram. | R1-R3 locked |
| 4 | **Audio-first FFmpeg assembly** | Decouple video and audio. Hard video cuts over continuous master audio mix (VO + music + SFX). Shot timing derived from VO script. No crossfades, no dynamic J/L-cuts. | R2 locked |
| 5 | **First-party APIs only** | No Apify/Ayrshare. YouTube Data API for comments + posting. Instagram Graph API for Reels + Story polls. TikTok Content Posting API for uploads. Start Meta App Review immediately (2-4 week lead time). | R2 locked |
| 6 | **Security model** | `.env` file (chmod 600) for API keys — NOT macOS Keychain (breaks with launchd). Hardcode JT's Telegram user ID (drop all other senders). $15/cycle cost kill-switch. 24-hour posting cooldown. Tailscale-only remote access. | R1-R2 locked |
| 7 | **AI disclosure** | Burn "AI Generated" watermark into video via FFmpeg. Set `is_aigc=true` on TikTok API. Add `#AI #MadeWithAI` to YouTube descriptions. | R2 locked |
| 8 | **Drop TikTok harvesting** | Post to TikTok but don't scrape comments. YouTube + Instagram are the voting platforms. TikTok is top-of-funnel distribution only. | R1-R2 locked |
| 9 | **Thematic Anchor narrative** | "Dungeon Master" architecture with guard rails: Character DNA + World Rules + Mystery Stack + Thematic Anchor. Every poll option must advance the thematic question. Mystery categories prevent thematic scatter. | R3 locked |
| 10 | **Model stack update** | NBP multi-reference (not Flux 2 LoRAs — deprecated Feb 27). Kling 3.0 I2V for character video. Veo 3.1 for environments. SeedDance 2.0 for dialogue. Flash 3.1 for previz. ElevenLabs for voice. Suno for music. | R1 correction |

---

## 2. PROOF OF CONCEPT PLAN

### Timeline: 8-10 days of work, ~3-4 weeks calendar (secondary priority)

### Step 1: Visual Benchmark (Manual) — 1 day
**What:** Use existing Starsend CLI to generate 5 shots for a test 30-second episode:
- 2 environment shots (Veo 3.1 T2V)
- 2 character shots (NBP keyframe → Kling 3.0 I2V)
- 1 detail/cliffhanger shot (NBP still)
- 1 ElevenLabs voiceover
- Assemble manually in Premiere Pro

**Go/No-Go Gate:** JT watches the video and says "I'd post this." If not, project is dead.

**Requires:** A minimal test premise (one character, one location, 30-second scene). Disposable or real.

### Step 2: FFmpeg Clone — 3 days (with 1-day buffer)
**What:** Take the exact raw assets from Step 1. Write `assembler.py`:
- Hard video cuts via concat demuxer
- Master audio track: VO + music + SFX blended via amix
- Shot timing from VO script
- ASS subtitle rendering (bottom third, safe zones)
- Poll overlay on final 3 seconds
- AI watermark in corner

**Go/No-Go Gate:** FFmpeg output is indistinguishable from the Premiere Pro edit AND renders on Mac in under 2 minutes.

### Step 3: Dry-Run Daemon — 2 days
**What:** Build `orchestrator.py` state machine with:
- All 10 CyclePhase states
- Telegram bot (polling mode, JT ID hardcoded)
- All commands: /status, /approve, /regenerate, /tweak, /reshoot, /pause, /resume, /costs, /force
- Mock API calls (copy Step 1 files instead of calling Kling)
- launchd plist for auto-start/restart
- SQLite state persistence

**Go/No-Go Gate:** Daemon runs 48 hours with zero crashes AND survives a mid-cycle kill + restart (reads SQLite, resumes from correct phase without double-charging APIs).

### Step 4: End-to-End Test — 2-3 days (with OAuth buffer)
**What:** Full production cycle with live APIs:
- Generate real shots via Starsend engine
- Assemble via FFmpeg
- Post to private YouTube channel
- Harvest comments, count votes
- Telegram bot handles /regenerate mid-cycle

**Go/No-Go Gate:** Full cycle completes, episode posts successfully, comments are harvested and counted correctly, AND JT successfully uses /regenerate to trigger a reshoot during the cycle.

---

## 3. UPDATED COST MODEL

### Per-Episode: $5-12

| Component | Low | High | Notes |
|-----------|-----|------|-------|
| Visual generation (5-7 shots, with retries) | $3.00 | $8.00 | 2 ENV ($0.20-0.80), 2-3 character I2V ($1.50-$4.50), 1-2 stills ($0.15-$0.40), retry buffer |
| Voice (ElevenLabs) | $0.10 | $0.30 | 30-second episode, minimal dialogue |
| Music (Suno) | $0.10 | $0.20 | Per-episode generation or rotating library |
| LLM calls (analysis + narrative + QC) | $0.15 | $0.50 | Sonnet analysis, Opus narrative, Gemini QC, Haiku vote counting |
| **Total per episode** | **$3.35** | **$9.00** | |
| **With 30% contingency** | **$4.35** | **$11.70** | |

### Monthly (10-15 episodes/month): $50-175

### One-Time Setup: ~$100-200
(Existing Mac Studio or new Mac Mini, API deposits, developer accounts)

---

## 4. DATA SCHEMA CONTRACTS

### audience_brief.json (Output of analyst.py)

```json
{
  "episode": 6,
  "collection_window": {"start": "ISO", "end": "ISO"},
  "poll_results": {
    "winning_option": 1,
    "options": [
      {"number": 1, "text": "...", "votes": 289, "percentage": 0.62},
      {"number": 2, "text": "...", "votes": 131, "percentage": 0.28},
      {"number": 3, "text": "...", "votes": 47, "percentage": 0.10}
    ],
    "total_votes": 467,
    "sources": ["youtube", "instagram"]
  },
  "comment_analysis": {
    "dominant_sentiment": "excited_curious",
    "recurring_themes": ["string"],
    "character_requests": ["string"],
    "flavor_elements": ["string"],
    "course_corrections": ["string"]
  },
  "engagement_metrics": {
    "total_views": 0,
    "total_comments": 0,
    "total_likes": 0
  }
}
```

### episode_script.json (Output of writer.py, input to producer.py)

```json
{
  "episode_number": 7,
  "title": "string",
  "duration_target_seconds": 30,
  "shots": [
    {
      "shot_number": 1,
      "description": "ECU — detail shot description",
      "type": "detail|character|dialogue|vfx_hero|environment|cliffhanger",
      "duration_seconds": 4,
      "characters_present": [],
      "generation_notes": "specific visual direction"
    }
  ],
  "voice_lines": [
    {"character": "protagonist", "text": "line", "direction": "whispered, tense", "timing_seconds": 2.0}
  ],
  "poll": {
    "question": "Short dramatic question",
    "options": ["Option A", "Option B", "Option C"]
  },
  "music_direction": "mood and instrumentation",
  "sfx_notes": ["footsteps on metal", "distant rumble"]
}
```

### series_state.json (Persistent narrative state)

```json
{
  "series": "starsend",
  "episode_current": 7,
  "protagonist": {
    "name": "string",
    "status": "current situation",
    "emotional_state": "string",
    "character_dna": {
      "behavioral_traits": [],
      "stress_response": "",
      "voice_pattern": ""
    }
  },
  "world_state": {
    "location": "string",
    "threat_level": "none|low|medium|high|critical",
    "established_facts": ["string"]
  },
  "narrative_engine": {
    "thematic_anchor": "Can you trust the thing that saved your life?",
    "mystery_categories": ["identity", "alliance", "the_creators"],
    "open_mysteries": [
      {"id": "m1", "category": "alliance", "clue_count": 2, "question": "Why did the drone lie about the atmosphere?"}
    ],
    "guardrail": "Every poll option MUST force the protagonist to either trust blindly or risk death to verify the truth."
  },
  "production_meta": {
    "total_episodes": 6,
    "total_cost": 0.00,
    "avg_cost_per_episode": 0.00
  }
}
```

---

## 5. KILL SWITCH PROTOCOL

### Via Telegram
```
/pause              → Daemon enters PAUSED state, stops all API calls, sends confirmation
/force idle         → Emergency reset to IDLE (skips current cycle)
```

### Via Tailscale SSH (nuclear option)
```bash
ssh joeturnerlin@100.105.59.118
launchctl unload ~/Library/LaunchAgents/com.starsend.studio.plist
# Daemon stops immediately. API calls in-flight will complete but no new ones start.
```

### Automatic Kill Switches
- **$15/cycle cost cap** — if SQLite cost tracker hits this, daemon halts and alerts JT
- **24-hour posting cooldown** — physically cannot post more than once per day per platform
- **3x module failure** → ERROR state → Telegram alert → daemon pauses
- **No internet** → all outbound calls fail → ERROR state after 3 retries

---

## 6. RISK REGISTER

| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| Meta App Review rejection/delay | Medium | Blocks IG posting | Start review now. YouTube + TikTok posting can proceed without IG. |
| YouTube API changes | Low | Breaks comment harvesting | Comment API is stable (10+ years). Monitor changelog. |
| Kling/Veo API pricing changes | Medium | Cost model breaks | Budget caps auto-halt. Shot router can swap models. |
| AI video quality plateau | Medium | Can't hit quality floor | PoC Step 1 validates this before any code is written. |
| Audience doesn't engage | Medium | No votes → no story progression | Fallback: JT makes the narrative decision. System works with zero votes. |
| TikTok API access denied | Low-Medium | Loses one distribution channel | TikTok is tertiary. YouTube + IG are sufficient. |
| Narrative drift (20+ episodes) | Medium | Story becomes incoherent | Thematic Anchor + Mystery Categories + guardrails. JT reviews every script. |
| launchd daemon instability | Low | Misses production cycles | SQLite state recovery. Crash-restart via launchd. |

---

## 7. DEPENDENCIES (Before PoC Can Start)

| Dependency | Status | Action |
|-----------|--------|--------|
| Test premise (1 character, 1 location, 30-second scene) | Not started | JT creates or Claude generates a disposable test premise |
| Character reference images for NBP | Not started | Generate via existing Starsend casting pipeline |
| ElevenLabs voice for test character | Not started | Clone or select from ElevenLabs library |
| YouTube channel (can be private for testing) | Likely exists | Verify API access |
| Meta App Review for Instagram | Not started | **Start immediately** — 2-4 week lead time |
| Telegram bot created | Not started | Register bot with @BotFather, get token |
| Mac Studio or Mac Mini available | Exists (Mac Studio) | Verify Starsend engine runs on Mac Studio via Tailscale |

---

## 8. MODEL BEHAVIOR ASSUMPTIONS (Verify Empirically)

| Assumption | Depends On | Verify During |
|-----------|-----------|---------------|
| NBP multi-reference maintains character consistency across 5-7 shots | Gemini 3 Pro Image cross-attention | PoC Step 1 |
| Kling 3.0 I2V from NBP keyframe has <30% retry rate for 4-6 sec clips | Kling 3.0 image conditioning quality | PoC Step 1 |
| Veo 3.1 environment shots are first-shot viable for 4-6 sec | Veo 3.1 T2V quality | PoC Step 1 |
| Hard video cuts + continuous audio mix feels professional | FFmpeg assembly approach | PoC Step 2 |
| launchd daemon survives multi-day operation with SQLite state | macOS launchd + SQLite WAL reliability | PoC Step 3 |
| Comment-based voting captures >80% of audience intent | Regex + Haiku classification accuracy | PoC Step 4 |

---

*Consultation complete. 3 rounds. All architectural decisions locked. PoC plan defined with hardened go/no-go gates. Hand to JT for approval, then begin Step 1.*
