---
name: global-bible
description: Sub-agent skill for Stage 1 Breakdown Pass. Synthesizes characters (with wardrobe phases and per-episode looks), locations, props, and lighting motifs into a canonical Global Bible. Merges incrementally with accumulated bible from prior batches. Supports look detection for cross-episode wardrobe/appearance changes.
allowed-tools: Read, Bash, Glob, Grep
argument-hint: "--episodes 1-10 [--project leviathan] [--merge] [--dry-run] [--detect-looks]"
---

# /global-bible — Global Bible Synthesis Sub-Agent

Reads all camera-tested episodes in a batch and synthesizes a canonical Global Bible containing characters, locations, props, and lighting motifs. This is Stage 1 of the 3-stage render extraction pipeline.

## What This Agent Does

1. Loads camera-tested JSONs from `data/camera_tested/ep_{NNN}.json`
2. Loads supplementary data from Recoil:
   - Character bible: `recoil/{project}/scripting/bible/characters.md`
   - Project config: `recoil/{project}/visual/project_config.json`
   - Existing breakdown: `recoil/{project}/visual/breakdown.json`
3. Calls extraction model (Opus 4.6 by default) with `BREAKDOWN_SYSTEM_PROMPT`
4. Validates output against `GlobalBible` schema from `lib/render_schema.py`
5. If `--merge`: merges with existing `state/visual/global_bible.json`
6. Saves to `state/visual/global_bible.json`

## Incremental Merge

When processing episodes in batches, the bible must merge incrementally:
- New characters are added; existing characters get updated phase ranges
- Locations are deduplicated by canonical `location_id`
- Props accumulate episode lists
- Lighting motifs merge by `motif_id`

The merge preserves human edits to the bible (e.g., manually corrected descriptions).

## Field Boundary Rules (Prompt Quality)

These rules prevent wardrobe duplication and narrative bleed in compiled prompts:

- **`visual_description`** = FACE AND BODY ONLY: age, build, skin, hair, facial features, scars, physical traits. NO wardrobe, accessories, or props. NO literary/narrative text ("the compact build of someone who survives by..." is meaningless to image models). Use concrete visual descriptors only.
- **`wardrobe_description`** = CLOTHING AND ACCESSORIES ONLY: everything worn or carried (respirators, counters, gloves, boots, jackets). Single source of truth for what the character wears. Never duplicate in `visual_description`.
- **`distinguishing_marks`** = permanent body features only (scars, tattoos, implants). Not clothing.
- **Opus enrichment**: When filling `[OPUS_ENRICHMENT]` placeholders in `visual_description`, write physical attributes that an image model can render. No narrative, no metaphor, no wardrobe.

### Prompt-Ready Distillations (for casting_state.json)

After bible enrichment, generate these compressed fields and write them to `casting_state.json` (NOT the bible — the bible is the creative source, casting_state is the production distillation):

- **`brief_visual`** (per character): 10-15 prompt keywords distilling `visual_description`. Focus on what distinguishes this character visually — the traits the model needs when a reference image already carries the likeness. Example: `"Towering armored figure, gunmetal blue chassis, exposed human face, pale blue eyes, military helmet"`. No narrative prose, no sentences — comma-separated visual tags.

- **`brief_wardrobe`** (per character, per phase): 10-15 prompt keywords distilling each phase's `wardrobe_description`. Focus on garments, materials, damage state, color. Example: `"Dirty tank top, rebreather at neck, canvas jacket at waist, oil-stained cargo pants, scuffed boots"`. Keyed by phase_id in a dict.

These fields prevent truncation artifacts when the prompt builder compresses 50-word bible prose into 10-word prompt slots. They're generated once per character during enrichment or casting, stored permanently, and preferred by the prompt builder when present.

## Look Detection (`--detect-looks`)

When `--detect-looks` is passed, the breakdown agent scans all episode scripts for wardrobe and appearance changes per character and outputs a `looks[]` array on each character entry. This is **additive** — the flat `appearance` and `visual_description` fields are preserved for backward compatibility.

### How it works

1. Loads all episode `.md` scripts from the project's `episodes/` or `scripting/episodes/` directory.
2. For each character, scans for look-change indicators near character mentions:
   - **Wardrobe:** "wearing", "changed into", "now in", "dressed in", "puts on", "armor", "helmet", "disguise", etc.
   - **Injury:** "blood", "torn", "burned", "wounded", "bandaged", "scarred", etc.
   - **Transformation:** "cybernetic", "augmented", "mutated", "prosthetic", etc.
3. When a character's described appearance shifts between episodes, a look boundary is proposed.
4. All characters default to a `"base"` look for their initial episode range.
5. The `looks[]` array is written into the bible's character entry.
6. An `episode_look_map.json` is auto-generated at `_pipeline/state/visual/episode_look_map.json`, mapping each character + episode to a look name.

### looks[] schema (v3)

```json
{
  "characters": {
    "JADE": {
      "appearance": "Athletic build, dark hair",
      "visual_description": "...",
      "looks": [
        {"name": "base", "description": "Engineering jumpsuit, utility belt, work boots", "episodes": [1,2,3], "trigger": null},
        {"name": "injured_ep08", "description": "Same jumpsuit, torn left sleeve, burn marks on face", "episodes": [8], "trigger": "torn in ep08"},
        {"name": "combat", "description": "Tactical vest, armored plates, helmet", "episodes": [7,8,9,10], "trigger": "armor in ep07"}
      ]
    }
  }
}
```

### episode_look_map.json

Auto-populated from `characters.{name}.looks[]`. Written to `_pipeline/state/visual/episode_look_map.json`:

```json
{
  "JADE": {"1": "base", "2": "base", "3": "base", "7": "combat", "8": "injured_ep08"},
  "KIT":  {"1": "base", "2": "base"}
}
```

### Usage

```bash
python3 recoil/visual/breakdown_agent.py episode.md /path/to/project --detect-looks
```

Or via the `/global-bible` skill:
```
/global-bible --episodes 1-10 --project leviathan --detect-looks
```

## Validation Rules

- All characters referenced in camera-tested shots must exist in the bible
- Every character must have at least one wardrobe phase
- Every character must have at least one look in `looks[]` (when `--detect-looks` is used)
- Phase `start_ep`/`end_ep` ranges must not overlap for the same character
- All locations must have a non-empty description
- `char_id` and `location_id` must be uppercase snake_case

## Output Schema

```json
{
  "project": "leviathan",
  "total_episodes": 60,
  "characters": {
    "JADE": {
      "char_id": "JADE",
      "display_name": "Jade",
      "visual_description": "...",
      "phases": [
        {"phase_id": "jade_lower_deck_salvager", "start_ep": 1, "end_ep": 30, ...}
      ],
      "episodes": [1, 2, 3, ...]
    }
  },
  "locations": {...},
  "props": {...},
  "lighting_motifs": [...]
}
```

## Failure Handling

- Pydantic validation error → retry with error feedback (up to 2 retries)
- After max retries → save to `data/review_queue.json` for human inspection
- Missing camera-tested files → log warning and skip (don't block)

## Implementation

Primary code: `orchestrator/ingest_pipeline.py` → `IngestPipeline.run_breakdown_pass()`
Schema: `lib/render_schema.py` → `GlobalBible`, `BibleCharacter`, `BibleLocation`, `BibleProp`
