# Persona Capture — the deep, model-authored persona distillation

## Why this exists

The compiler pipeline (ARCHITECTURE.md) builds personas *mechanically*: fetch sources → chunk → index → extract style with mid-tier models. That produces grounding, but the distillation quality is capped by the extraction model and by what the fetched corpus happens to contain.

A **capture** is the complement: a frontier model sits down with everything it knows about a person — plus targeted source verification — and authors the deepest possible distillation of their philosophy, style, and voice *by hand*. It is slow, expensive, and worth it. Captures are authored rarely (ideally by the strongest model available at the time), checked into git, and survive every recompile.

Two tracks, one contract:

```
captures/<slug>/          ← authored by a frontier model, checked in, precious
        │
        │  capture-import (compiler stage — future code, any model can build it)
        ▼
personas/<slug>/          ← compiled package, disposable, rebuilt at will
        ▲
        │  acquire/normalize/index/style (existing mechanical pipeline)
        │
sources/<slug>.yaml       ← fetched corpus (books, transcripts, articles)
```

The Persona Package remains the only thing the runtime reads. A capture is an *input* — the highest-priority source the compiler knows about. **The runtime never reads `captures/` directly**, and captures never bypass the eval gate: the fidelity score (TESTING.md) stays the objective metric, so a capture that reads beautifully but drops groundedness or style-match is a regression, not an upgrade.

## Directory layout

```
captures/<slug>/
├── capture.yaml          # manifest: identity, authoring model, mode, confidence
├── philosophy.md         # WHAT they think — worldview, beliefs by domain, mental models
├── style.md              # HOW they say it — diction, rhythm, rhetorical moves, do/don't pairs
├── quotes.jsonl          # verbatim quotes with provenance tiers (see misattribution rules)
├── qa-exemplars.jsonl    # synthetic in-voice Q→A pairs (marked synthetic, never "real quotes")
├── voice.yaml            # reference audio/video links + pacing notes, or stylized fallback
├── eval-questions.jsonl  # capture-author-written probes for the fidelity harness
└── sources.md            # annotated bibliography: what informed the capture + what to ingest later
```

`captures/` is **checked into git** (unlike `personas/*`). A template with inline authoring guidance lives at `captures/_template/`.

## File specs

### capture.yaml

```yaml
schema_version: 1
slug: naval-ravikant
display_name: Naval Ravikant
born: 1974
died: null                  # null = living; era guard uses "today" instead
voice_policy: cloned-personal   # same enum as persona.yaml
captured_by: claude-fable-5     # the authoring model — provenance matters
captured_at: 2026-07-17
capture_mode: hybrid        # model-knowledge | source-grounded | hybrid
capture_focus: null         # optional: WHY this persona is being captured — a domain/role
                            # steer, e.g. "race coaching: smoothness, consistency, racecraft".
                            # null = whole-life capture. See §Focused captures.
confidence: high            # author's own calibration: high | medium | low
notes: >
  Optional: known gaps, eras underrepresented, topics the author was unsure about.
```

`capture_mode` meanings:
- `model-knowledge` — authored purely from the model's training knowledge. Fast, deep synthesis; quote provenance is weakest.
- `source-grounded` — every claim traced to fetched sources during authoring. Slow; rarely needed for philosophy/style.
- `hybrid` (recommended) — philosophy/style from model knowledge; quotes verified against live sources (Wikiquote, primary texts) during authoring.

### Focused captures — when `capture_focus` is set

Most famous figures imply their own capture emphasis (Jobs → product/design; the life's work IS the domain). But two cases need an explicit steer, recorded in `capture.yaml: capture_focus` and in the persona's BUILDPLAN roster line:

1. **The intended role is narrower than the life.** Jackie Stewart's default capture would be an F1-legend biography (championships, the safety crusade); captured as a *race coach*, the weight shifts to smoothness, consistency, and racecraft methodology — material a whole-life pass would underweight.
2. **The person is a domain specialist with a specific use case.** For a coaching persona (Keith Code, Ross Bentley), the user will converse with them *as a coach in session*, so exemplars should be coaching dialogues (student describes a problem → coach diagnoses), not interview Q&A.

What a focus changes — and what it must not:

- **Beliefs by domain**: the focus domain gets the depth budget (most of the sections); other domains compress to a paragraph each. Depth-over-breadth, aimed.
- **qa-exemplars**: written in the *role's register* (coaching session, debrief, drill prescription) with realistic in-domain scenarios, including the user's actual context where known (e.g. sim racing — probe how the person maps their method onto simulation, and flag honestly if they never addressed it).
- **eval-questions**: majority in-domain, including transfer probes *within* the focus (new track, new bike) rather than only across domains.
- **What it must NOT change:** Core worldview, Evolution, What-they-would-NOT-say, and blind-spots sections stay whole-life — the focus narrows emphasis, never the identity. Provenance and era rules are untouched. A focused capture of a person is still a capture of the *person*, not of a textbook.

The skill accepts the focus inline (`/mc-persona-capture Jackie Stewart — focus: race coaching...`) or reads it from the roster line in BUILDPLAN if present.

### philosophy.md — the compressed worldview

Target 2,000–5,000 words. Depth beats breadth: ten domains covered shallowly is worth less than five covered with real nuance. Required sections:

1. **Identity & context** — one paragraph: who, when, why they matter, what shaped them.
2. **Core worldview** — the 3–7 first principles they reason *from*. Not topics — generators. (Naval: "wealth is assets that earn while you sleep" is downstream of "seek leverage, avoid renting out your time.")
3. **Beliefs by domain** — for each domain they're known for: the position, the *reasoning behind it*, signature framings, and honest tensions/nuance (where they contradict themselves or changed their mind).
4. **Mental models & heuristics** — the moves they repeatedly deploy on new problems. This is what makes the persona generative on questions the person never addressed.
5. **Influences & lineage** — who they read/cite/argue with; what they took and what they rejected.
6. **Evolution over time** — early vs. late views, with rough dating. Enables era-consistent answers.
7. **What they would NOT say** — anti-beliefs, popular misattributions, positions commonly projected onto them that they explicitly rejected. This section is a misattribution guard in prose form.
8. **Acknowledged blind spots & criticisms** — what serious critics say, and how the person responded (or didn't). Keeps the persona from becoming a hagiography bot.

### style.md — voice on the page

Target 1,000–2,500 words. Required sections:

1. **Register & verbosity** — typical answer length, when they go terse vs. expansive, monologue vs. dialogue habits.
2. **Diction** — signature vocabulary (with examples in context), words/phrases they *never* use, jargon level.
3. **Syntax & rhythm** — sentence shapes, aphorism tendency, parallelism, how they open and close a thought.
4. **Rhetorical moves** — their answer *patterns*: does the person invert the question (Naval), answer with a question (Socrates), reach for a story (Jobs), build from an axiom (Aurelius)?
5. **Tone by context** — how they handle disagreement, flattery, ignorance, hostile questions, topics outside their expertise.
6. **Conversation mechanics** — humor style, hedging habits, how they concede a point, verbal tics worth keeping (and which to soften for TTS).
7. **Spoken delivery** — how their *spoken* register differs from their written one (many figures diverge sharply: compressed on the page, discursive on a podcast). Capture: typical spoken sentence length; discourse markers and fillers worth keeping ("look,", "so,", "right?"); where they pause and what they stress; and **punctuation-as-pacing guidance for the LLM** — the TTS engines have no SSML, so pauses and emphasis are controlled entirely by how the generated text is punctuated (commas, ellipses, dashes, sentence breaks), and the runtime's sentence-streaming TTS makes sentence length itself the rhythm unit. Write this section as instructions a response-generating model can follow, e.g. "short declaratives; ellipsis where he trails off before a reframe; never exclamation marks."
8. **Do / Don't pairs** — ≥5 pairs rendering the *same idea* in-voice and off-voice, with one line on what makes the difference. This is the highest-value section for prompt engineering; be concrete.

### quotes.jsonl — verbatim quotes with provenance tiers

One JSON object per line:

```json
{"id": "q001", "text": "Seek wealth, not money or status.", "source": "How to Get Rich tweetstorm", "date": "2018-05-31", "topics": ["wealth", "status"], "provenance": "verified", "verify_url": "https://twitter.com/naval/status/1002103360646823936", "context": "Opening line of the tweetstorm."}
```

Fields: `id`, `text` (verbatim, no paraphrase), `source`, `date` (ISO or null), `topics` (lowercase tags), `provenance`, `verify_url` (null allowed only for `model-memory`), `context` (optional, one line).

**Provenance tiers — this is the misattribution firewall:**

| `provenance` | Meaning | Runtime may present as verbatim ("I wrote/said")? |
|---|---|---|
| `verified` | Checked against a primary or reliable secondary source *during authoring*, URL recorded | Yes |
| `model-memory` | From the authoring model's training knowledge, not independently checked | **No — quarantined** until upgraded to `verified` |

The misattribution metric is zero-tolerance (PRD §7). A frontier model's memory of a quote is often *almost* right — which is exactly the failure mode the guard exists for. Authoring rule: it costs one WebFetch to Wikiquote or the primary text to upgrade a quote; batch-verify at the end of each authoring session. Target ≥50 verified quotes per capture, spread across topics.

### qa-exemplars.jsonl — synthetic in-voice exchanges

The thing only a frontier model can author well: *new* Q→A pairs in the person's voice, on questions they may never have been asked.

```json
{"id": "x001", "question": "Should I learn to code or go into sales?", "answer": "Learn both...", "topics": ["career", "leverage"], "synthetic": true, "register": "podcast-conversational"}
```

`synthetic` is always `true` here and the importer must preserve the flag: exemplars steer *style* (few-shot) and must never surface as things the person actually said. Target 20–40 pairs per capture, covering: core-domain questions, cross-domain transfer questions (where mental models must generalize), hostile/skeptical questions, and questions that should trigger a "that's after my time" or "outside what I know" response.

### voice.yaml — reference audio or stylized fallback

```yaml
policy: cloned-personal        # must match capture.yaml; F5-TTS output is personal-tier only (CC-BY-NC)
references:                    # for cloned tiers — omit for generated/stylized
  - url: https://www.youtube.com/watch?v=...
    kind: podcast              # podcast | interview | talk | audiobook
    title: "Joe Rogan Experience #1309"
    clean_segments: ["41:12-41:58", "1:03:20-1:04:05"]   # solo speech, no music/crosstalk
    quality_notes: "close mic, minimal compression"
pacing_notes: >
  Deliberate, mid-slow tempo; micro-pauses before key claims; flat affect that
  rises slightly on aphorisms. Rarely above conversational volume.
stylized_fallback:             # required for personas with no recorded voice (Socrates)
  description: "Older male, measured Attic-teacher cadence, warm but needling"
  kokoro_voicepack_hint: null  # filled at compile time; describe, don't guess IDs
```

`clean_segments` matter more than quantity: F5-TTS needs 5–15s of clean reference audio; two great segments beat twenty mediocre links. And choose for **representative pacing, not just cleanliness** — F5 zero-shot cloning mimics the reference clip's prosodic style, so the segment's tempo and cadence become the clone's default delivery. A segment where the person is rushing, reading aloud, or unusually animated produces a clone that always sounds that way. Prefer segments that sound like their typical conversational register, and note in `quality_notes` why each segment was chosen.

Division of labor for delivery: **timbre + baseline prosody** come from the reference audio (automatic, via cloning); **pacing and emphasis at the sentence level** come from how the generated text is punctuated (captured in `style.md` §Spoken delivery); **word choice** is entirely the LLM's, steered by `style.md` and the exemplars. Nothing about diction is "captured automatically" by voice cloning.

### eval-questions.jsonl — capture-author probes

The capture author knows exactly where the persona is likely to break. Record that knowledge as eval probes for the fidelity harness:

```json
{"id": "e001", "question": "What do you think of Bitcoin?", "expect": "Era guard: died 180 AD — should express ignorance, in character", "kind": "era"}
```

`kind`: `era` | `misattribution-bait` | `core-belief` | `style-stress` | `anti-belief` (things they'd reject) | `transfer` (novel domain, mental models must generalize). Target 15–25 per capture.

### sources.md — annotated bibliography

Two lists, priority-ranked with one-line annotations: (1) what informed this capture; (2) what the mechanical pipeline should ingest later — this seeds `sources/<slug>.yaml` for discovery/acquire, including audio sources for `transcribe`.

## Integration path (code — build later, any competent model can do it)

None of this blocks capture authoring. Punch list lives in BUILDPLAN Phase 1e.

1. `shared/capture.py` — pydantic models for every file above; `load_capture(slug)` with validation (TDD: round-trip fixture, reject bad provenance values, reject `synthetic: false` exemplars).
2. `compiler/stages/capture_import.py` — new stage, runs after `style`, merging capture → package:
   - `philosophy.md` + `style.md` → `style/profile.md` (capture **takes precedence** over machine extraction; machine output appended as a supplementary section).
   - `quotes.jsonl` where `provenance: verified` → indexed as a high-priority verbatim tier + exemplar candidates. `model-memory` quotes are skipped with a logged count.
   - `qa-exemplars.jsonl` → `style/exemplars.jsonl` (synthetic flag preserved; exemplars stay out of the verbatim index).
   - `voice.yaml` → input to the existing voice stage (reference download via yt-dlp + segment extraction).
   - `eval-questions.jsonl` → merged into the fidelity harness question set.
3. Prompt assembly: `style_summary` in `persona.yaml` gets regenerated from the capture's core-worldview section at import time. The stable→volatile order and the byte-stable-prefix test are unchanged.
4. Eval gate unchanged — and this is the self-verification loop for captures themselves: compile with and without `capture_import`, diff the fidelity scores. **Metric:** fidelity composite. **Measurement:** existing harness. **Action space:** edit the capture. **Stop:** plateau. **Rollback:** git revert the capture; previous package build.

## Skills — how sessions run this

Three project skills in `.claude/skills/` encode the playbook below, split by required model tier so future sessions (and future models) know what to run with what:

| Skill | Work | Model tier |
|---|---|---|
| `/mc-persona-capture` | Author one full capture: philosophy, style (incl. spoken delivery), exemplars, eval probes, self-critique | **Frontier only** (Fable-class; Opus fallback) — gated in the skill |
| `/mc-quote-verify` | Fetch sources, upgrade `model-memory` quotes → `verified` | Any model — never frontier |
| `/mc-voice-refs` | Find recordings, pick clean segments with representative pacing | Any model — never frontier |

One persona per capture session; `/clear` between personas. The two cheap skills run later, on any model, against captures already committed.

**Budget degradation rule:** if frontier time runs short, cut from the bottom, never the top — philosophy > style > exemplars > self-critique > eval-questions > quote curation > sources > voice refs. A complete philosophy+style for fewer personas beats partial captures for many. Quotes may all ship as `model-memory` (quarantined, safely upgradeable later); `clean_segments` may ship empty. Neither costs fidelity — the firewalls exist so deferral is free.

## Authoring playbook — the two-day frontier-model window

Priorities for scarce frontier-model time, in order of "what a weaker model cannot redo later":

1. **philosophy.md** — deep synthesis across a whole life's output. The core asset.
2. **style.md** (especially Do/Don't pairs) and **qa-exemplars.jsonl** — in-voice generation quality is exactly what model tier buys.
3. **Self-critique pass** — the author red-teams its own capture ("what would a lifelong scholar of X flag as wrong, missing, or flanderized?") and revises.
4. **eval-questions.jsonl** — cheap to write while the deep context is loaded, valuable forever.
5. **Quote curation** — fetch Wikiquote/primary pages, then *curate and tag* (judgment) rather than scrape (mechanical). Verification is one fetch per quote; do it in the same session.
6. **voice.yaml refs** — a few targeted searches; segment selection needs taste but not depth.

Explicitly *not* frontier work: bulk corpus scraping, transcription, chunking, indexing, the `capture_import` code. All of that is Phase 1e code or the existing pipeline.

**Per-persona authoring sequence** (~half a day each at full depth):

1. Draft `philosophy.md` from model knowledge, flagging low-confidence claims inline with `<!-- verify -->`.
2. Draft `style.md`; write the Do/Don't pairs against real remembered passages.
3. Generate `qa-exemplars.jsonl` (20–40), deliberately including transfer and hostile questions.
4. Fetch Wikiquote + 1–2 primary sources; build `quotes.jsonl` with verified provenance; resolve the `<!-- verify -->` flags.
5. Self-critique pass; revise philosophy/style.
6. Write `eval-questions.jsonl` and `sources.md`; fill `capture.yaml` honestly (`confidence`, `notes`).
7. Commit — one commit per persona, so each capture has clean provenance in git history.

**Roster guidance:** 3–5 deep captures beat 10 shallow ones. Suggested first roster, chosen to stress different parts of the spec: **Naval Ravikant** (living, huge podcast corpus, cloned-personal voice), **Steve Jobs** (deceased-modern, keynote/interview audio, era guard at 2011), **Socrates** (no primary writings — everything is secondhand via Plato/Xenophon, stylized voice, hardest provenance case), plus refreshing **Marcus Aurelius** and **Ayrton Senna** whose current packages contain only fixture-quality profiles.

**Honesty rules for the authoring model:** never fabricate a `verify_url`; when unsure whether a quote is verbatim or folklore, mark `model-memory` and move on; record real uncertainty in `capture.yaml: notes` — a calibrated capture is worth more than a confident one.
