Skip to content

feat(archives): auto-generated war narrative (#274)#446

Merged
elfensky merged 1 commit into
developfrom
feature/war-narrative
Jun 28, 2026
Merged

feat(archives): auto-generated war narrative (#274)#446
elfensky merged 1 commit into
developfrom
feature/war-narrative

Conversation

@elfensky

Copy link
Copy Markdown
Owner

Closes #274.

What

A collapsible War Narrative on each season's /archives page — a chronological, in-world chronicle generated in the Ministry of Truth propaganda voice. Pure frontend: a transform over data already supplied by getCampaign, no schema/DB/query changes.

How

  • buildWarNarrative(data) — pure helper → ordered [{day, text}] beats: opening → faction arrivals (introduction_order + per-faction first_seen) → cascade runs collapsed via findAllCascades → per-event field reports → a getWarOutcome cap. Defensive (empty → [], reduce-min war_start fallback).
  • NarrativeSection.jsx — native <details>/<summary> collapsible, hide-when-empty (like Player Engagement), data-umami-event="archive-narrative-toggle". Wired into ArchivesClient.
  • 12 unit tests, incl. an Illuminate-cascade regression.

Sample (from the test fixture)

Day 1: The war begins. By order of the Ministry of Truth, every citizen is a soldier and every soldier is a statistic.
Day 6: The Illuminate enter the war. The Ministry assures all citizens this was anticipated, scheduled, and is going entirely according to plan.
Day 13: A devastating cascade. The Bugs push through 4 regions in a single day. Reports of panic have been reclassified as enthusiasm.
Day 48: Super Earth falls. The Illuminate have won. The Ministry assures surviving citizens that this defeat was both temporary and, in hindsight, inspirational.

Review verification

Built by an implementation agent; reviewed + an integration bug caught and fixed during review: the cascade beat bypassed the article-stripping helper, so an Illuminate cascade rendered "The The Illuminate push through" (the enum name is "The Illuminate"). Fixed to resolve via factionName(cascade.factionIndex) + added a regression test.

✅ lint · typecheck · test:unit (1515) · build — all pass (node 24).

⚠️ Hold before merge

  • Voice/tone is subjective — please eyeball the Ministry phrasing; easy to tweak in buildWarNarrative.mjs.
  • Sequencing: merging to develop bumps to the next version and folds into the open v0.60.0 release PR Release v0.60.0 #445. Recommend merging this after v0.60.0 ships.

🤖 Generated with Claude Code

A collapsible, in-world "war narrative" for each season's /archives page —
a chronological chronicle generated in the Ministry of Truth propaganda voice
from existing getCampaign data (no schema/DB/query changes).

- buildWarNarrative(data): pure helper → ordered [{day, text}] beats — opening,
  faction arrivals (introduction_order + first_seen), cascade runs collapsed via
  findAllCascades, per-event field reports, and a getWarOutcome cap. Defensive:
  empty → []; reduce-min war_start fallback (no Math.min spread).
- NarrativeSection.jsx: native <details>/<summary> collapsible, hide-when-empty,
  data-umami-event="archive-narrative-toggle". Wired into ArchivesClient after
  the Player Engagement section.
- 12 unit tests incl. an Illuminate-cascade regression for the article-stripped
  faction name ("The Illuminate", not "The The Illuminate").

Verified: lint, typecheck, test:unit (1515), build all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@elfensky elfensky merged commit 7f2ea0b into develop Jun 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant