plans

Future improvement — Chapter Character Beats (potential v1.9)

Status: backlog. Not committed to ship. Discussed 2026-05-05 after the v1.5–v1.8 planning push. Recommendation at the time: don't ship next — pause, run a v1.8 improve-all-behind on a real season, and confirm whether multi-character flatness is actually the limiting issue before adding another planning layer. If it is, this is the next thing to build. If the limiting issue turns out to be something else (sentence rhythm, dialogue density, emotional pacing), build that instead.

The gap

After v1.8 we have five chapter-level planning layers + nine critics:

LayerWhat it provides
Bible (canon)each character's overall season-level arc + rolling current_state (updated via deltas)
Knowledge layer (v1.5)per-chapter what the reader learns
Spine (v1.6)per-chapter scene shape (opening_image / central_turn / closing_image)
Stakes (v1.7)per-chapter wants / obstacle / cost — for the central character only
Frameworkact-level structure

The chapter writer sees each major character's overall arc + rolling current_state via the bible block. What they don't explicitly receive is a per-chapter beat for each major character — "in chapter 4 specifically, here's what shifts for Evelyn, what Marcus does and why, where Pell ends up emotionally."

The failure mode this would address: multi-character chapters where side characters feel flat or static because the writer wasn't told what's pressing on them this chapter and defaults to making them backdrops. AI is bad at multi-character density.

Why it's smaller than the gaps already filled:

  • Bible deltas already update each character's current_state after each chapter — so cross-chapter continuity is enforced
  • continuity_auditor checks against the bible's per-character state
  • subtext_doctor flags character-state inconsistency
  • stakes covers the chapter's central character

The remaining gap is specifically about the other major characters in scenes where multiple appear.

Proposed shape

Same pattern as v1.5/v1.6/v1.7:

Migration 143

alter table story_episodes
  add column if not exists chapter_character_beats jsonb;

alter table story_episodes
  add column if not exists chapter_character_beats_generated_at timestamptz;

JSONB shape

[
  {
    "character_key": "evelyn_harper",  // matches bible.characters[].key
    "entry_state": "still angry from the meeting; replaying what Marcus said",
    "shift": "finds the second key in the drawer and lies about it to Marcus",
    "exit_state": "the lie is pressing; she's calculating whether he believed it"
  },
  {
    "character_key": "marcus_vance",
    "entry_state": "pretending not to know about the audit; reading her",
    "shift": "asks about the drawer too directly; sees her flinch",
    "exit_state": "now suspects she found something but won't ask again"
  }
]

One entry per major character that appears or is referenced in the chapter. Skip introduced_only characters and walk-ons.

Service: apps/backend/src/services/chapter-character-beats.ts

  • computeChapterCharacterBeatsForSeason(seasonId) — single GPT-4o-mini pass over bible + chapter plan + knowledge layer + spine + stakes (so beats compose with what's already planned). Returns one entry per (chapter × major character).
  • hasChapterCharacterBeats(seasonId) — for lazy-compute gating
  • buildChapterCharacterBeatsBlock(beats) — renders the prompt block

Prompt injection

In season-novel-chapter.ts, inject AFTER stakes:

bible → reader window → scene compass → pressure → CHARACTER BEATS → framework directive

The block frames the beats as marching orders for the non-central characters specifically — the central character is already covered by chapter_stakes. Possibly only inject the beats for characters who aren't the chapter's central one, to avoid redundancy.

Critic update

Extend delivery_auditor (v1.8) or add a sibling multi_character_density critic that checks: "for each character listed in chapter_character_beats, did the prose deliver their entry/shift/exit?" Same pattern as the existing prose-vs-plan audit.

UI

Mirror the v1.5/v1.6/v1.7 admin buttons:

  • 🎭 Regen character beats button in EpisodesAdminModal toolbar
  • POST /api/story-seasons/:id/regenerate-chapter-character-beats (super-admin)

Platform version bump

v1.9 — adds chapter_character_beats to the planning chain + (optionally) multi_character_density critic to the default set.

Cost

~$0.005/season for the GPT pass (one call, all chapters). Independent of per-chapter prose generation cost.

Tradeoffs

For:

  • Closes a real failure mode (multi-character flatness)
  • Natural completion of the planning hierarchy (bible.arc → chapter_character_beats → bible delta)
  • Composes with existing critics

Against:

  • We're at 5 planning layers already; system prompt is getting heavy
  • Diminishing returns set in
  • The bible's current_state already provides per-character snapshots; this layer is partly redundant
  • Could over-constrain the writer for characters who organically take a different shape mid-chapter

Decision criterion: After running v1.8 in production for at least one season, if the dominant failure mode in critique findings + reader feedback is "side characters feel flat" or "multi-character scenes lack texture," ship this. If it's something else, ship that.

Pre-work needed

Before implementing:

  1. Run a v1.8 improve-all-behind on a real season (e.g., the Turing Logs current season)
  2. Listen + read the result
  3. Tally findings from delivery_auditor + first_reader + subtext_doctor — what's the dominant pattern?
  4. If multi-character flatness shows up consistently, proceed with this plan.
Chapter Character Beats — Docs | HiveJournal