ADR-029: Chapter synopsis as dual-source field¶
Status: Accepted
Date: 2026-04-23
Context: The campaign dashboard previously displayed chapter_intro for the upcoming chapter — Coach J's hand-authored 3-5 sentence atmospheric prose. This created a redundancy: when the player clicked Start, the AI-generated preamble_blocks ran, often re-narrating the same setup in greater detail. Players read the same narrative twice, in two places, with the dashboard version reading like an unfinished version of the preamble. Spotted during Apr 22 playtest debrief — the team felt the dashboard text didn't tell them what they were about to do, only what was happening atmospherically.
Decision¶
Add a new chapter_synopsis field to campaign_chapters that holds a 1-2 sentence (max 35 words), plain-language summary of the chapter's central tension or decision. The dashboard reads chapter_synopsis first, falling back to chapter_intro if missing. Original chapter_intro is preserved untouched as a backup and as the source for future re-derivations.
Static arcs and reactive arcs derive synopsis from different sources but both surface in the same dashboard slot:
- Static arcs: synopsis is generated once per arc from the existing chapter_intro + scenario description, written to the campaign_chapters row. Done in batch via scripts/generate-chapter-synopses.ts for all 152 chapters across 22 arcs.
- Reactive Worlds: synopsis is generated per-playthrough as part of the master_doc.arcTrajectory[chapterN].synopsis field. Master doc generation prompt was updated to require the field. Dashboard reads from master_doc when the chapter row's synopsis is null.
Rationale¶
The dashboard needed a "what is this chapter about" field that is structurally different from the chapter's narrative content. Three constraints shaped the design:
- Don't lose the existing prose. Coach J's
chapter_introis still useful as backup or for future re-derivation. Adding a separate field instead of overwriting preserves the original. - Match Coach J's solo quick-round quality bar. Solo quick rounds open with crisp role + situation language ("You're Director of Marketing at a 60-person company..."). The static campaign chapters lacked this orientation — synopsis brings them in line.
- Reactive arcs have no pre-authored content. Their chapters are fully procedural. The synopsis must be generated per playthrough alongside the master doc, since the chapter's specific cast, setting, and tensions only exist in that master doc instance.
Alternatives Considered¶
- Truncate
chapter_introto first sentence on the dashboard. Hacky — the first sentence isn't necessarily a synopsis. The intro is narrative prose, often opening atmospherically. - Hide
chapter_introon the dashboard entirely; let title + Recap do all orientation. Cleaner but lost a useful information slot. Some chapters benefit from a one-line "what's this about" that title alone can't convey. - Replace
chapter_introwith synopsis (single-field). Destructive — would lose the existing prose, no backup, no fallback path during transition. - Store synopsis on the campaign instance, not the arc. For static arcs this would force per-campaign generation when the content is identical for all players. The dual-source approach (arc-level for static, campaign-level via master_doc for reactive) lets each arc type use the right scope.
Discussion¶
The first instinct after the Apr 22 playtest was to add a "Quick Context" block at the top of every scenario description (case study page). That shipped first and addresses orientation for the per-chapter decision page. But the team's actual confusion lived earlier — at the campaign dashboard, where players were reading narrative prose without knowing what world they were in or what choice was coming.
Initial fix attempt: a one-shot "welcome to this world" modal showing the arc description on first arrival. Replaced quickly after Jonathan flagged that modals get dismissed and forgotten — persistent context wins. Replaced with the "About this Campaign" collapsible card.
Once the world-level context was solved, the per-chapter narrative duplication on the dashboard surfaced as a separate problem. Hence this ADR. The chapter_synopsis field complements the About card: About gives world context (always available), Recap gives "what just happened" context (Ch.2+), Synopsis gives "what's coming next" context (current chapter teaser). Three distinct orientation layers, each in its right slot.
For reactive Worlds, an alternative was to skip the per-playthrough synopsis and just hide the teaser entirely. Rejected because reactive arcs need more orientation help than static arcs, not less — players can't rely on familiarity with a known curated story.
Consequences¶
- DB schema: new
chapter_synopsis TEXTcolumn oncampaign_chapters. Backfilled for static arcs; populated lazily for reactive arcs via master_doc. - Dashboard rendering: prefers
chapter_synopsis, falls back tomaster_doc.arcTrajectory[chapterN].synopsisfor reactive, thenchapter_introas final fallback. - AI prompt updates:
generate-arc/route.ts(custom Worlds creation),campaign-master-doc.ts(curated Worlds master doc generation), andscripts/generate-chapter-synopses.ts(static arc backfill) all require/produce the synopsis field. - Cost: static arc backfill cost ~$0.50 (152 chapters × ~$0.003). Reactive World synopsis is generated as part of an existing master_doc call, no additional API cost.
- Watch for: quality drift if model produces atmospheric prose instead of synopsis. The prompt explicitly bans this with worked examples, but verify on first reactive World playthrough.
Key files:
- src/types/database.ts — CampaignChapter.chapter_synopsis and ReactiveArcMasterDoc.arcTrajectory[chapterN].synopsis typed
- src/app/(app)/campaigns/[id]/page.tsx — dashboard rendering with dual-source fallback
- src/app/api/campaigns/generate-arc/route.ts — custom World creation prompt
- src/lib/ai/campaign-master-doc.ts — curated/reactive World master doc prompt
- scripts/generate-chapter-synopses.ts — static arc backfill tool