Synced from virality/stages/01-source-analysis.md in content-extraction skill on 2026-05-18. Edit upstream in the skill; this file is overwritten on next sync.

Stage 1 — Source Analysis

Pure inventory of what’s IN the source. NO scoring, NO opinions, NO clip proposals. The sub-agent’s S1 produces this so S2 has structured input to compose candidates from. Daniel can also grep this file directly.

Output file: <session>/source-analysis.md Hard cap: 150 lines.

Required inputs

S1 refuses to run without:

  • <session>/transcript.txt — verbatim contract
  • <session>/transcript-words.json — word-level timing
  • <session>/silence-map.json — Phase 1 silence-detect output (silence-detect runs at parent Step 4 — BEFORE this sub-agent)

If any missing: emit only the header + a MISSING-INPUT: <name> line, exit. Don’t produce a partial inventory.

Output structure (fixed schema)

# Source Analysis — <session-id>
 
## Source map
- Source: <filename> | duration: Xs | fps: Y | transcribed: <backend> | language: <auto-detected>
- Silence map: N ranges, Zs total silence, threshold <dB>dB · pre <Nf> · post <Nf> · min-strip <Nf>
- Whisper segments: N | word count: M
 
## Inventory
 
| beat# | start | end  | dur  | quote (first 8 words…)              | tags                                    |
| 01    |  7.2  | 18.4 | 11.2 | "I set myself a limit now"          | declarative, named-decision, P5         |
| 02    | 18.4  | 22.0 |  3.6 | "And that was quite daunting"       | filler-prefix, hedge                    |
| 03    | ...   | ...  | ...  | ...                                 | ...                                     |
 
## Tag legend
- **Pillars:** P1 (intimate-domestic-ai) · P2 (privacy-first-architecture) · P3 (hardware-tangibility) · P4 (ai-companion-philosophy) · P5 (ambitious-startup-realness) · P6 (co-founder-bridge) · P7 (process-transparency)
- **Beat-types:** declarative, named-decision, named-number, named-artifact, two-beat, vulnerability, tool-naming, categorical-reframe, contrarian, restart-pause, filler, outro-cta, transition
- **Source-position:** head (first 30s) | mid | tail-30s (last 30s)
- **Silence-classification:** rule-m-hold (>2s, preserved), filler-pause (<2s, cut)
 
## Silence-map summary
| range# | silence_start | duration | classification          |
| 01     |  4.38         | 0.62s    | filler-pause            |
| 02     |  6.92         | 6.92s    | filler-pause            |
| 03     | 47.12         | 3.16s    | rule-m-hold (preserved) |
| ...    |               |          |                         |
 
## Tail-30s candidates (auto-flagged Rule A)
- beat 14 @ 142.0s — "<verbatim quote, full sentence>" — auto-Tier-1
- beat 17 @ 158.4s — "<verbatim quote>" — categorical-reframe
 
## Source-shape signals
- Total speech: Xs (Y%)
- Total silence (post-trim): Zs (W%)
- Tail-30s contains: N tier-1 candidates / M categorical reframes / K vulnerability beats
- Episode-anchor opener detected: yes/no — beat 01 starts with "<phrase>"
- Outro CTA detected: yes/no — beat last starts with "<phrase>"

Beat segmentation rules

A beat = an atomic semantic unit. Split source into beats by:

  1. Sentence boundaries first. Whisper segments often span multiple sentences. Split at . ! ? (with whitespace-tolerant matching).
  2. Sub-split on conjunction-led pivots. “And that’s the thing” / “But here’s what” / “So basically” — each starts a new beat.
  3. Combine restart-pauses. “Yeah, so…” + actual content = ONE beat tagged restart-pause + the content’s natural beat type.
  4. Don’t split mid-rhetorical-hold. Rule M holds (>2s “this…” pauses) keep their preceding + following sentence in ONE beat tagged rule-m-hold.

Beat numbers are sequential from 01. Stable across re-runs (deterministic from sentence segmentation).

Tagging rules (per beat)

Apply tags by pattern detection. A beat can have multiple tags.

Pillar tags (P1-P7) — match against _brand/pillars.md trigger patterns. Apply at most ONE pillar per beat (the dominant one). If two pillars compete, pick the one with stronger trigger match.

Beat-type tags:

  • declarative — stand-alone declarative sentence (subject + verb + complete thought, no qualifying clauses)
  • named-decision — “I set myself X” / “I decided to” / “I chose” + specific
  • named-number — contains a non-round number (3,247 / 14 hours / version 100 / etc.)
  • named-artifact — references a specific shipped/built thing (the website, the friend, version 100)
  • two-beat — has two-beat cadence structure (period or en-dash separating two short clauses)
  • vulnerability — first-person past about failure / near-miss / fear / surprise (Pattern A from references/shortform-virality.md)
  • tool-naming — names a specific tool stack (Claude, Figma, agents, ffmpeg, Whisper) — Pillar 7 affinity
  • categorical-reframe — rejects a widely-held belief OR reframes existing assumption (“we are not merely…”, “this can’t be it”)
  • contrarian — opens with “everyone says X” / “stop doing Y” / similar
  • restart-pause — leads with “yeah, so…” / “okay basically” / restart artifact
  • filler — restating, conjunction-led continuation without new substance, vague modifier
  • outro-cta — series-anchor close (“let’s get started”, “thanks for watching”)
  • transition — bridges two beats but carries no own substance (cut candidate)

Source-position tags:

  • head — start_seconds < 30
  • tail-30s — start_seconds > duration - 30
  • mid — between

Silence-classification rules

For each range in silence-map.json:

  • duration > 2.0s AND falls inside a Whisper segment → rule-m-hold (preserved)
  • duration <= 2.0sfiller-pause
  • duration > 2.0s AND falls between Whisper segments → inter-beat-pause (natural breath)

Tail-30s auto-flag (Rule A enforcement)

For every beat whose start_seconds > (source_duration - 30):

  • If beat has any of declarative / categorical-reframe / two-beat / named-decision / vulnerability tags
  • Auto-flag as candidate for tail-as-opener
  • Surface in “Tail-30s candidates” section with full quote (not just first 8 words)

S2 receives this list and MUST include at least 1 tail-as-opener candidate in candidates.md.

What S1 deliberately does NOT do

  • Does NOT score beats. No tier-1/2/3 ranking, no hook strength.
  • Does NOT propose clips. Inventory only.
  • Does NOT pre-filter. Even filler beats get listed (they’re inputs to S2’s drop decisions).
  • Does NOT write to cut-plan.json. Read-only against transcript + silence-map.
  • Does NOT enforce verbatim — that’s S2’s gate. S1 just lists.

Hard gates for S1 output

  • ≤150 lines total. If source is dense, prioritize Inventory section + Silence-map summary + Tail-30s candidates. Compress beat-type tags if needed.
  • Beats numbered sequentially without gaps.
  • Every beat has start, end, duration, quote-prefix, ≥1 tag.
  • Tag-legend section MUST appear before Inventory section is consulted (cross-reference).

Verification (S1 output sanity)

After S1 emits, verify:

  1. Total beats * average dur ≈ source duration ± 10% (catches segmentation errors)
  2. Sum of beat durations + sum of silence durations ≈ source duration ± 5%
  3. ≥1 beat tagged with each of: P1-P7 (pillars covered) — flag if 0 pillars detected
  4. ≥1 tail-30s candidate flagged (or explicit “no tail-30s candidates” note)
  5. Whisper segments count matches transcript-words.json segment count

If any check fails: surface as S1-INTEGRITY-WARNING at top of source-analysis.md. Don’t block; just flag.