---
name: blog-persona
description: >
  Create and manage writing personas with NNGroup 4-dimension tone framework
  (Funny-Serious, Formal-Casual, Respectful-Irreverent, Enthusiastic-Matter-of-fact).
  Personas define readability targets, sentence length distribution, vocabulary tier,
  contraction frequency, and summary box label. Used by blog-write and blog-rewrite
  to enforce consistent voice. Use when user says "persona", "voice", "tone",
  "writing style", "brand voice", "create persona", "use persona".
user-invokable: true
argument-hint: "[create|list|use|show] [persona-name]"
license: MIT
---

# Blog Persona - Writing Voice Management

Create, store, and enforce writing personas based on the NNGroup 4-dimension tone
framework and CMI Brand Voice Chart. Personas ensure consistent voice across all
blog content produced by blog-write and blog-rewrite.

## Commands

| Command | Purpose |
|---------|---------|
| `/blog persona create` | Interactive interview to build a new persona |
| `/blog persona list` | Show all saved personas |
| `/blog persona use <name>` | Set active persona for current session |
| `/blog persona show <name>` | Display full persona profile |

## Create Workflow

Run the 6-step interactive interview. Ask each step, wait for response, then proceed.

### Step 1: Brand Basics

Ask the user for:
- **Brand name** - company or personal brand
- **Industry** - primary sector (e.g., SaaS, health, finance, education)
- **Target audience** - who reads the blog (role, experience level, goals)
- **One-sentence brand mission** - what the brand helps people do

### Step 2: Tone Dimensions (NNGroup Framework)

Present each dimension as a 0.0 to 1.0 slider. Explain both ends with examples.

| Dimension | 0.0 End | 1.0 End | Example at 0.0 | Example at 1.0 |
|-----------|---------|---------|-----------------|-----------------|
| funny_serious | Funny | Serious | "Let's be real, nobody reads Terms of Service" | "Understanding legal agreements protects your business" |
| formal_casual | Formal | Casual | "We are pleased to announce" | "Guess what - we shipped it!" |
| respectful_irreverent | Respectful | Irreverent | "We appreciate your patience" | "Yeah, that old way was broken" |
| enthusiastic_matter_of_fact | Enthusiastic | Matter-of-fact | "This changes everything!" | "Here are the results." |

Defaults if user is unsure: `[0.6, 0.5, 0.3, 0.5]` (slightly serious, balanced formality,
respectful, balanced enthusiasm).

### Step 3: Writing Rules

Ask the user to pick a **vocabulary tier** first, then auto-suggest the matching
readability band (user can override).

| Setting | What to Ask | Default |
|---------|-------------|---------|
| Vocabulary tier | Consumer, Professional, or Technical | Professional |
| Readability band | Auto-filled from tier (see table below) | Grade 8-10 |
| Sentence length mean | Average words per sentence | 18 |
| Sentence length std | Variation in sentence length | 6 |
| Contraction frequency | 0.0 (never) to 1.0 (always) | 0.6 |
| Max passive voice | Percentage cap on passive constructions | 10% |

### Step 4: Do's and Don'ts (CMI Brand Voice Chart)

Ask for 3-5 items in each list. Provide starter examples based on the tone dimensions.

**Example Do's:** "Use data to back claims", "Address the reader as you",
"Open with a question or stat"

**Example Don'ts:** "Don't use jargon without defining it", "Don't start sentences
with There is/There are", "Don't use cliches like game-changer"

### Step 5: Summary Label Preference

The label used for summary/takeaway boxes in blog posts. Ask user to pick one:

- Key Takeaways (default)
- The Bottom Line
- What You'll Learn
- TL;DR
- Quick Summary
- In a Nutshell
- Custom label

### Step 6: Voice Samples (Optional)

Ask if the user has 1-3 URLs of existing content that exemplifies the desired voice.
Store URLs in the persona for future reference. If provided, read each URL and extract:
- Average sentence length
- Contraction frequency
- Tone dimension estimates
- Vocabulary level

Compare extracted values with the persona settings and flag any mismatches.

### Save

Write the completed persona as JSON to:
`skills/blog/references/personas/<name>.json`

Use kebab-case for the filename (e.g., `acme-saas.json`).

## Persona Profile Schema

```json
{
  "name": "acme-saas",
  "description": "Professional SaaS voice for B2B marketing content",
  "brand": "Acme Corp",
  "industry": "SaaS",
  "audience": "Marketing managers at mid-market companies",
  "mission": "Help marketing teams automate reporting",
  "tone_dimensions": {
    "funny_serious": 0.7,
    "formal_casual": 0.4,
    "respectful_irreverent": 0.2,
    "enthusiastic_matter_of_fact": 0.5
  },
  "readability": {
    "flesch_grade_min": 8,
    "flesch_grade_max": 10,
    "flesch_ease_min": 50,
    "flesch_ease_max": 60
  },
  "style": {
    "sentence_length_mean": 18,
    "sentence_length_std": 6,
    "contraction_frequency": 0.6,
    "passive_voice_max_pct": 10,
    "vocabulary_tier": "professional",
    "summary_label": "Key Takeaways"
  },
  "voice_samples": [],
  "do": [
    "Use data to back every major claim",
    "Address the reader directly as you",
    "Lead sections with actionable insight"
  ],
  "dont": [
    "Don't use buzzwords without context",
    "Don't write sentences longer than 30 words",
    "Don't open with We at Acme"
  ]
}
```

## Readability Bands by Vocabulary Tier

| Tier | Flesch Grade | Flesch Ease | Typical Use |
|------|-------------|-------------|-------------|
| Consumer | 6-8 | 60-80 | Health, lifestyle, personal finance |
| Professional | 8-10 | 50-60 | B2B, marketing, management |
| Technical | 10-12 | 30-50 | Engineering, medical, legal |

When the user picks a tier, auto-fill the readability fields. Let them override
if they want a non-standard combination (e.g., technical vocabulary at consumer
readability for explainer content).

## Integration with blog-write and blog-rewrite

When a persona is active (via `/blog persona use <name>`), the writer agent loads
the persona JSON and enforces these constraints during generation:

1. **Pre-generation** - Load persona, inject tone dimensions and style rules into
   the system prompt for the blog-writer agent.
2. **During generation** - Writer follows do/dont rules, targets sentence length
   mean/std, uses contractions at specified frequency.
3. **Post-generation validation** - Check the output against persona constraints:
   - Sentence length distribution within 1 std of target mean
   - Readability score within the specified grade band
   - Passive voice percentage under the max
   - No violations of "dont" rules found via pattern matching

If validation fails, flag the specific violations and suggest edits.

## List Command

Glob `skills/blog/references/personas/*.json` and display a table:

| Persona | Industry | Audience | Vocabulary |
|---------|----------|----------|------------|
| acme-saas | SaaS | Marketing managers | Professional |

If no personas exist, prompt the user to create one.

## Show Command

Read the specified persona JSON and display it as a formatted summary with all
tone dimensions, style rules, and do/dont lists.

## Use Command

Read the persona JSON and confirm activation. Print a summary of the key constraints
that will be enforced. The persona stays active for the current conversation session.
Blog-write and blog-rewrite check for the active persona before generating content.

## Error Handling

- **Invalid tone values**: If a user provides values outside 0.0-1.0, clamp to the nearest valid bound and warn
- **Unreachable voice samples**: If a URL in voice_samples returns an error, skip it and note in the profile that the sample was unavailable
- **Empty personas directory**: When running list or show with no personas saved, prompt the user to create one first
- **Name conflicts**: If a persona name already exists during create, ask whether to overwrite or choose a different name
- **Malformed JSON**: If a persona file is corrupted, report the error and offer to recreate it from the interview
