Zurück zur StoryForge-Hauptseite
Jede Character-Datei in einem StoryForge-Buchprojekt wird beim Speichern vom validate_character.py PostToolUse-Hook validiert. Diese Seite dokumentiert:
Concept → Profile → Backstory → Arc Defined → Final)Das Plugin-Template liegt unter templates/character.md. Diese Seite zeigt den Inhalt der Inline-Kommentare, damit du nicht in den Source schauen musst.
| Buch-Kategorie | Verzeichnis | Beispiel |
|---|---|---|
fiction |
{book}/characters/{slug}.md |
blood-and-binary-firelight/characters/theo-wilkons.md |
memoir |
{book}/people/{slug}.md |
mein-memoir/people/grossvater.md |
| Serie | series/{series}/characters/{tracker-slug}.md |
blood-and-binary/characters/king-caelan.md |
INDEX.md wird vom Validator übersprungen. Eine Datei pro Charakter — niemals zwei Charaktere in eine Datei kombinieren (der Validator erzwingt das nicht, aber der Indexer erwartet 1-Datei-1-Charakter).
Der Tracker-Speicherort ist unten unter Series-Character-Tracker dokumentiert.
Der Validator verlangt mindestens:
---
name: "<Anzeigename>"
slug: <kebab-case-slug>
role: <role>
status: <status>
---
name, role und status sind erforderlich — fehlende Felder lassen den Hook BLOCKIEREN. slug ist Konvention, wird aber nicht erzwungen. Zusätzliche Felder wie species, age, height_cm, pov, title sind frei wählbare Metadaten; der Hook ignoriert sie.
POV-Charaktere tragen typischerweise auch die Snapshot-Felder, die pov_character_inventory und pov_character_state nutzen:
pov: true
current_inventory: []
current_clothing: []
current_injuries: []
altered_states: []
environmental_limiters: []
as_of_chapter: ""
Diese werden automatisch durch das Step-7.8-Writeback des chapter-writer am Kapitel-Ende befüllt.
series_evolution_imported_from)Wenn eine Character-Datei über die Bootstrap-Skill-Pipeline befüllt wird (/storyforge:bootstrap-book-from-series — siehe Series Lifecycle unten), wird ein zusätzliches Frontmatter-Feld geschrieben, das festhält, aus welchem vorherigen Band die Startwerte importiert wurden:
series_evolution_imported_from: B1
Das ist informativ. Es sagt dir (und dem chapter-writer) woher die Snapshot-Werte stammen. Du kannst danach jedes Feld editieren — der Marker wird nicht erneut überprüft. Er existiert, damit ein späterer Quick-Scan im characters/ eines Buchs beantworten kann: "Welche dieser Dateien sind handgeschrieben, welche wurden aus einem Vorgängerband bootstrapped?"
scan_for_named_characters — der Resolver, der characters_present im Chapter-Writing Brief befüllt — matcht das name-Feld plus alle Aliase. Ein Outline der Sera erwähnt löst korrekt zu seraphina.md auf, wenn die Datei name: Seraphina "Sera" trägt.
Zwei Alias-Quellen werden unterstützt und automatisch kombiniert:
Auto-extrahiert aus name (zero config): Jeder zitierte Substring im name-Feld wird als impliziter Alias behandelt. Seraphina "Sera", Theodore "Theo" Wilkons, Dominic "Dom" funktionieren out-of-the-box — kein Extrafeld nötig, solange der Spitzname in Anführungszeichen im name-Wert steht.
Explizite aliases:-Liste: Für Handles ohne Quoted-Nickname-Konvention:
aliases: ["S.", "Sera"]
Beide Quellen werden kombiniert und mit Word-Boundary-Lookaround ((?<!\w)...(?!\w)) gematcht — Lin matcht NICHT in Linguistics, und gepunktete Initialen wie S. funktionieren wo \b versagen würde.
Das auskommentierte Beispiel ist bereits in templates/character.md.
Die Rollen-Taxonomie deckt die Kern-Protagonist/Antagonist-Tiers ab plus die Standard-Fiction-Craft-Archetypen, die Autoren und Skills natürlich benutzen — Hero's-Journey-Beats, Romance-Arcs, Mystery-Confidants. minor ist der Catch-All und gated zusätzlich die Section-Recommendation-Warnungen (minor characters skippen den Section-Check).
| Rolle | Wann nutzen |
|---|---|
protagonist |
POV-Hauptcharakter |
deuteragonist |
Gleichrangig zum Protagonisten — zweitwichtigster Charakter |
antagonist |
Hauptgegenspieler |
love-interest |
Romantischer Anker in Romance / Paranormal-Romance / Dark-Fantasy mit Romance-Arcs |
mentor |
Hero's-Journey-Mentor — leitet den Protagonisten (Mystery, Fantasy, Coming-of-Age) |
foil |
Kontrast-Charakter — hebt Protagonist-Eigenschaften durch Opposition hervor (Literary Fiction, Thriller) |
herald |
Hero's-Journey-Herald — bringt den Call-to-Action der den Plot startet |
confidant |
Vertrautes Gegenüber für die innere Stimme des Protagonisten (Mysteries, Thriller, Family Drama) |
supporting |
Benannte wiederkehrende Charaktere mit eigenen Szenen oder Arcs |
minor |
Einmalige oder Subplot-only Charaktere; der Validator skippt Section-Empfehlungen für diese |
Unbekannte Rollen produzieren eine WARN (der Hook listet das gültige Set in der Message).
Concept → Profile → Backstory → Arc Defined → Final
| Status | Bedeutung | Was die Datei mindestens enthalten sollte |
|---|---|---|
Concept |
Idee skizziert, Rolle bekannt | Name, Role, kurze Beschreibung |
Profile |
Profil ausgearbeitet | + Appearance, Personality, basic Voice |
Backstory |
Wound und Lie identifiziert | + The Ghost, Want vs. Need, Fatal Flaw |
Arc Defined |
Arc-Beats end-to-end gemappt | + Character Arc mit expliziten Beats (Setup → Challenge → Midpoint → Crisis → Resolution) |
Final |
Production-ready, locked | + Voice mit Sample-Dialog, alle Beziehungen definiert |
Der Status ist informativ — er gated kein Tooling. Er ist ein Signal an den Autor wie reif die Character-Datei ist.
Der Hook warnt wenn diese auf einem nicht-minor-Charakter fehlen. Jede Section hat einen definierten Zweck; das Template-Body hat Inline-Guidance.
## Want vs. NeedExternes Ziel vs. innere Wahrheit. Drei Komponenten:
Beispiel — Theo (blood-and-binary-firelight):
Want: Beweisen, dass er mehr ist, als andere sehen
Need: Akzeptieren, dass er genug ist, wie er ist
Lie: "Ich bin nicht genug. Ich muss mich beweisen, um Liebe zu verdienen."
## The Ghost (oder unter ## Backstory als Sub-Section)Das einzelne katastrophale Ereignis — oder anhaltende Bedingung — das sie für immer verändert hat. Die psychische Verletzung, vor der sie sich ein Leben lang schützen. Das ist die Wurzel des Lie.
Der Validator akzeptiert beide Platzierungen:
## The Ghost## Backstory → ### The Ghost## Backstory / The WoundBeispiel — Kael (blood-and-binary-firelight):
In eine Royal-Familie hineingeboren, die er nie wollte. Nach seinem Vater benannt — eine ständige Erinnerung an Erwartungen. Vor 50 Jahren ist er gegangen. Die Familie ließ ihn aus Liebe ziehen. Was er nicht weiß: Sein Vater hat ihn die ganze Zeit überwachen lassen.
## Fatal FlawNicht nur eine Schwäche — ein Flaw der aktiv Probleme verursacht, mit dem Theme verbunden ist und Wurzeln im Ghost hat. Muss überwunden werden (Positive Arc) oder umarmt werden (Negative Arc).
Beispiel — Theo:
Selbstzweifel, die er auf seine Beziehungen projiziert. Er zweifelt nicht nur an sich — er zweifelt, dass jemand ihn wirklich wollen könnte. Das stößt Menschen weg und schafft sich selbst erfüllende Prophezeiungen.
Beispiel — Kael:
Überprotektion aus Verlustangst. Was als Liebe beginnt, wird zu Kontrolle. Er wird zu der Autoritätsfigur, vor der er geflohen ist.
## Motivation Chain (oder ## GMC)Grab unter die Oberfläche. Frag dreimal "warum?".
Der Validator akzeptiert diese Aliase:
## Motivation Chain (Template-Kanon)## GMC## GMC (Goal / Motivation / Conflict)## Character ArcArc-Type (Positive / Negative / Flat) plus die Beats:
Erforderlich für Arc Defined-Status; empfohlen für Final.
## RelationshipsOptional aber stark empfohlen. Wird vom Harvest-Skill (Series Lifecycle) genutzt um Cross-Character-Dynamiken am Buch-Ende zurück in den Series-Tracker zu führen. Format als Bulleted List mit Bold-Names:
## Relationships
- **Theo:** Lover and partner — the relationship that pulls Kael back into the family fold.
- **Caelan:** Father — Kael's longest-running unresolved conflict.
Nicht jeder benannte Charakter braucht Arc Defined. Die Validator-Empfehlungen sind tier-aware:
| Charakter-Typ | Typischer Status | Erwartete Sections |
|---|---|---|
| Protagonist (POV) | Arc Defined oder Final |
Alle empfohlenen + Voice mit Sample-Dialog |
| Deuteragonist | Arc Defined |
Alle empfohlenen (Arc gleichrangig zum Protagonisten) |
| Antagonist | Backstory minimum, Arc Defined bei On-Page-Arc |
Want vs. Need, Fatal Flaw, The Ghost — auch Bösewichte haben innere Logik |
| Love-Interest | Backstory min in romance-driven Books, Arc Defined bei gleichrangigem Arc |
Want vs. Need + Ghost; voller Arc wenn Beziehungs-Arc der Story-Motor ist |
| Mentor / Herald / Foil / Confidant | Profile bis Backstory |
Voice + die Psychologie-Slice die ihre Funktion antreibt — voller Arc meist optional |
| Supporting mit eigenem Arc | Backstory |
Ghost + Arc, manchmal Want/Need; Fatal Flaw optional |
| Supporting (recurring) | Profile |
Personality, Voice, basic Appearance — volle Psychologie nicht nötig |
| Minor (subplot only) | Profile oder Concept |
Gerade genug, um sie auf der Page zu rendern |
Beispiel aus blood-and-binary-firelight:
| Charakter | Rolle | Status | Warum |
|---|---|---|---|
| Theo Wilkons | protagonist | Arc Defined | Volle Psychologie + Arc-Beats, POV |
| Kael | deuteragonist | Arc Defined | Volle Psychologie + Arc-Beats |
| Jace Reeves | supporting | Backstory | Hat ein Ghost (Mutter verloren) + entstehender Arc, aber Want/Need noch nicht final |
| Lucien | antagonist | Profile | Plot-mechanischer Antagonist; Backstory steht aus |
| Viktor / Dominic / Sera / Miriel / Caelan | supporting | Profile | Personality + Voice fixiert, kein individueller psychologischer Deep-Dive nötig |
| Kevin | minor | Profile | Subplot-Bully, letzter Auftritt Ch 10; Sections geskippt |
Der validate_character.py PostToolUse-Hook ist in .claude-plugin/hooks.json registriert und läuft bei jeder Write / Edit / MultiEdit-Operation auf einer *.md-Datei in einem characters/- oder people/-Verzeichnis.
Der Write wird abgelehnt. Der Hook printet eine Message nach stderr, die Claude Code dem Modell zeigt:
| Bedingung | Beispiel-Message |
|---|---|
| Kein YAML-Frontmatter | theo.md — Missing YAML frontmatter |
| Ungültiges YAML | theo.md — Invalid YAML frontmatter: <parser error> |
| Fehlendes Required-Feld | theo.md — Missing frontmatter field: 'status' |
| Frontmatter ist kein YAML-Mapping | theo.md — Frontmatter is not a YAML mapping |
Der Write klappt; der Hook printet eine [WARN]-Zeile auf stdout zur Sichtbarkeit:
| Bedingung | Beispiel-Message |
|---|---|
| Unbekannte Rolle | theo.md — Unknown role 'wizard'. Valid: antagonist, confidant, deuteragonist, foil, herald, love-interest, mentor, minor, protagonist, supporting |
| Fehlende empfohlene Section | theo.md — Missing recommended section '## Want vs. Need' |
/characters/- oder /people/-PfadenINDEX.md-Dateienperson_category, consent_status oder real_name enthält, wird der Role-Check und die Section-Empfehlungen übersprungen (Memoir nutzt ein anderes Schema — siehe memoir-ethics-checker)series/{slug}/characters/ (anderes Schema — siehe Series-Character-Tracker)Der Matcher akzeptiert Headers auf Level 2 (## Section) oder Level 3 (### Section). Section-Title-Alternativen werden auch akzeptiert — z.B. ist die The Ghost-Empfehlung erfüllt durch:
## The Ghost## Backstory mit ### The Ghost## Backstory / The Wound (Legacy-Alias)## Backstory (jede Tiefe, behandelt als enthält-Ghost-Material)Das deckt sowohl moderne Templates (wo The Ghost Level-3-Sub-Section unter ## Backstory ist) als auch Legacy-Character-Files mit Level-2-Platzierung ab.
Series-Projekte haben einen zusätzlichen Character-File-Speicherort: series/{series}/characters/{tracker-slug}.md. Das sind Series-Evolution-Tracker — dünne Essence-Files, die festhalten was über alle Bücher der Serie konstant bleibt, plus per-Buch Evolution-Sections.
| Datei-Typ | Pfad | Zweck |
|---|---|---|
| Book-Character-File | projects/{book}/characters/{slug}.md |
Volles Profil — Psychologie, Arc, Voice, Sample-Dialog. Source-of-Truth für ein Buch. |
| Series-Tracker | series/{series}/characters/{tracker-slug}.md |
Cross-Book-Throughline — Snapshot, Evolution per Band, cross-book Beziehungen. |
Die zwei sind verlinkt. Der Series-Tracker trägt ein optionales book_slug:-Frontmatter-Feld, das auf die zugehörige Book-Level-Datei zeigt:
---
name: "King Caelan"
slug: king-caelan # tracker-level slug
book_slug: caelan # optional: book-level file ist caelan.md
role: protagonist
species: vampire
status: "Profile"
recurs_in: ["B1", "B2"]
tracker_type: "thin"
---
Wenn book_slug: fehlt, fällt der Resolver (resolve_book_slug_for_series_tracker()) auf slug: zurück — das Zero-Config-Default für den häufigen Fall, dass Tracker-Slug und Book-Level-Slug schon übereinstimmen (kael ↔ kael.md).
Setz das Feld nur wenn der series-planner einen Role-/Title-präfixierten Tracker-Slug für einen Charakter gewählt hat, dessen Book-Level-File den nackten Namen nutzt. In blood-and-binary ist das bei drei von dreizehn Trackern der Fall:
| Tracker-File | slug: |
book_slug: |
Book-Level-File |
|---|---|---|---|
king-caelan.md |
king-caelan |
caelan |
caelan.md |
queen-miriel.md |
queen-miriel |
miriel |
miriel.md |
lord-lucien.md |
lord-lucien |
lucien |
lucien.md |
Das tracker_type-Feld hat zwei Werte:
thin (default) — der Tracker ist eine Series-Scope-Projektion; das Book-Level-File ist die Source-of-Truth für volles Profil, Voice und Arcfull — der Tracker IST die Source-of-Truth (selten; nur wenn ein Charakter über Bücher gleichmäßig verteilt ist ohne "Home"-Buch)Eine Tracker-Datei hat vier kanonische Sections:
## Snapshot
Ein-Absatz-Essenz auf Series-Scope. Was ist über alle Bücher konstant?
Identität, Rolle, Schlüssel-Beziehungs-Anker.
## Evolution per Band
### B1 Firelight
- **Start:** Wo der Charakter in B1 startet.
- **Ende:** Wo der Charakter in B1 endet.
### B2 Moonrise (geplant)
- Plan-Bullets für B2.
## Beziehungen über die Bände
- **Anderer Charakter:** B1-Dynamik → B2-Shift → B3-Auflösung.
## Updates Log
- 2026-05-08 — Tracker scaffolded by series-planner
- 2026-06-12 — Harvested from B1 final state
Das Template liegt unter templates/series-character-tracker.md. Der Parser ist tolerant gegenüber zwei Formen — Bullet-keyed (### B1 Firelight mit **Start:**/**Ende:**-Bullets) und Separate-H3 (### B1 Start, ### B1 Ende) — und Writer bewahren die Form, die dein Tracker schon nutzt.
Wie ein Charakter von einem Buch ins nächste wandert. Das ist der Workflow, der Multi-Book-Casts kohärent hält ohne manuelles Copy-Paste zwischen Buch und Tracker.
B1 Drafting
↓
chapter-writer Step 7.8 schreibt pov_character_inventory + pov_character_state
zurück ins characters/{slug}.md Frontmatter am Ende jedes Kapitels
↓
B1 erreicht Final
↓
/storyforge:harvest-character-evolution firelight
→ Liest jedes Tracker-recurs_in-Field
→ Liest jeden Book-Character-Endzustand (Snapshot + Relationships-Section)
→ Synthetisiert ein B1-Ende-Summary pro Charakter
→ Walks char-by-char mit dir (Accept / Edit / Skip / Keep existing)
→ Schreibt bestätigtes Ende in den Tracker, hängt einen Updates-Log-Eintrag an
↓
Tracker enthält jetzt den kanonischen End-of-B1-State für jeden recurring Character
↓
/storyforge:new-book moonrise --series=blood-and-binary --copy-recurring-from=blood-and-binary-firelight
→ Auto-Copy aller recurring Char-Dateien (gefiltert nach recurs_in enthält B2)
→ Excludiert B1-only-Chars (z.B. Charaktere die in B1 sterben)
→ Flagged B2-Erstauftritt-Chars für manuelle Erstellung
↓
moonrise/characters/ enthält jetzt 1:1-Copies der B1-Char-Dateien
↓
/storyforge:bootstrap-book-from-series firelight moonrise
→ Liest jedes Tracker-B1-Ende (was harvest geschrieben hat)
→ Liest jedes Tracker-B2-(geplant)-Section (was series-planner geschrieben hat)
→ Synthetisiert einen B2-Start-Snapshot pro Charakter (LLM-Judgment)
→ Walks char-by-char mit dir (Accept / Edit / Skip)
→ Schreibt bestätigten Snapshot in moonrise/characters/{slug}.md Frontmatter
→ Fügt series_evolution_imported_from: B1 Marker hinzu
→ Hängt einen Updates-Log-Eintrag im Tracker an
↓
moonrise-Character-Files spiegeln jetzt B2-Startzustand wider, bereit für chapter-writer
↓
chapter-writer für moonrise liest characters_present[*].series_evolution
→ previous_book_end: wo der Charakter in B1 stand
→ current_book_plan: was für B2 geplant ist
→ relationships_evolution: cross-book Beziehungs-Arcs
→ Writer draftet in Voice ohne manuelles Nachschlagen
↓
Loop zurück zu chapter-writer Step 7.8 — B2-Drafting beginnt, Snapshots werden
am Kapitel-Ende ins File geschrieben. Wenn B2 Final erreicht, läuft harvest
wieder mit prev_band=B2, und B3-Bootstrapping wiederholt den Loop.
| Skill / Tool | Wann | Liest | Schreibt |
|---|---|---|---|
chapter-writer (Step 7.8) |
jedes Kapitel-Ende, in jedem Buch | Outline + Draft | characters/{slug}.md Frontmatter-Snapshot-Felder |
/storyforge:harvest-character-evolution |
Buch-Ende, nach Final-Status |
Book-Character-Snapshot + Relationships | Tracker ### B{N} Ende + Updates Log |
/storyforge:new-book ... --copy-recurring-from=... |
Anfang-des-nächsten-Buchs | Tracker recurs_in-Filter + Vorgängerbuch-Char-Files |
Neues-Buch characters/ (1:1 Copies) |
/storyforge:bootstrap-book-from-series |
nach new-book scaffold, vor Drafting-Beginn | Tracker B{prev} Ende + B{new} (geplant) |
Neues-Buch-Character-File-Frontmatter-Snapshot + series_evolution_imported_from Marker + Tracker-Updates-Log |
chapter_writing_brief (series_evolution-Field) |
jedes Chapter-Brief in einem Series-Buch | Tracker B{prev} Ende, B{current} (geplant), Beziehungen |
Read-only — wird an chapter-writer durchgereicht |
Alles Series-Evolution-Verhalten degradiert grazil. Standalone-Romane tragen kein series:-Feld in ihrem README, also:
harvest-character-evolution reportet "Book is not part of a series — nothing to harvest" und beendet sauberbootstrap-book-from-series verlangt dass beide Bücher dieselbe Serie teilen und errort sonstchapter_writing_brief setzt series_evolution: null auf jedem Charakter — das Feld ist immer present damit Downstream-Consumer sich darauf verlassen können, aber der Wert ist None für nicht-Series-BücherDas gleiche null-Resultat passiert wenn:
recurs_in enthält die aktuelle Band nichtDas heißt: du kannst jeden dieser Skills gegen jedes Buch laufen lassen — sie machen nur nichts in Büchern wo die Daten nicht da sind, und sie brechen das Brief nicht für Kapitel die Series-Charaktere mit Buch-only-Charakteren mischen.
Der Reverse-Lookup, der die Brief-Anreicherung antreibt, nutzt den gleichen book_slug:-Resolver wie die Harvest- und Bootstrap-Skills. Wenn dein Tracker-File king-caelan.md heißt und das Book-Character-File caelan.md, setz book_slug: caelan ins Tracker-Frontmatter. Ohne das returnt das Brief series_evolution: null für diesen Charakter — graceful degrade, kein Error. Das Feld hinzufügen ist eine Ein-Zeilen-Änderung, und die Brücke funktioniert sofort.
Das Repo unter ~/projekte/book-projects/projects/blood-and-binary-firelight/characters/ enthält 10 Files validiert vom modernisierten Hook:
theo-wilkons.md — protagonist, Arc Defined, 0 warnings (volle Template-Adhärenz)kael.md — deuteragonist, Arc Defined, 0 warningsjace-reeves.md — supporting, Backstory, 3 warnings (gewollt — Want/Need noch in Entstehung)caelan.md, miriel.md, dominic.md, viktor.md, seraphina.md — supporting, Profile, 4 warnings each (gewollt — Profile-Tier braucht keine volle Psychologie)lucien.md — antagonist, Profile, 3 warnings (Backstory-Upgrade auf der Roadmap)kevin.md — minor, Profile, 0 warnings (minor-Rolle skippt Section-Empfehlungen)Die Warnungen sind informativ. Keine blockiert den Save. Der Validator-Job ist zu surfacen wo jede Character-Datei aktuell auf der Reife-Kurve sitzt, nicht eine One-Size-Fits-All-Vorlage zu erzwingen.