Files
gupi-osint-board/docs/narrative-todo.md
gitprovandClaude Opus 4.8 ddb3a386f0 Add story-graph narrative system (campaigns, editors, runtime)
Introduce the narrative layer as a directed story-flow graph: an authored
campaign a player walks node by node, replacing the interim slot/chapter model.

Schema (migrations 015-021):
- mysteries, global NPC templates + named poses, per-user playthroughs
- story_nodes, terminals, utterances (the flow graph and dialogue trees)
- clean cutover: retire slot cutscenes/chapters/seen_dialogue

Runtime:
- New Game creates a playthrough bound to the JWT identity (dev test-user fallback)
- advance() walks the graph cutscene -> dialogue -> level -> ..., auto-skipping gates
- branching dialogue: player choices route out through node terminals

Admin authoring:
- NPC editor: upload named poses to the gupi MinIO bucket
- mystery graph editor: vertical node canvas, wiring, entrypoint, delete-by-click
- dialogue crafter: utterance tree, Tab to add child, 1/2 speaker, undo

Content authored via the manifest importer / admin panel and seeded for Glass
Harbour. MinIO added to the dev stack; dev container runs in development mode.

Also includes a folder-widget simplification (removes open/close) and a
resolveUserId auth helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 15:37:46 +02:00

7.6 KiB
Raw Permalink Blame History

Narrative layer: campaigns, NPC cutscenes, and authoring

This roadmap covers the narrative layer end to end: the campaign that chains levels into a mystery, the NPCs / poses / cutscenes the player watches between levels, and the admin authoring panel that lets a game designer build all of it in-app. Work generally proceeds top to bottom.

Design intent. These mysteries are real-world scam cases that must actually be investigated to be understood. Such cases cannot be simplified, they can only be staged for didactic discovery into levels.

The LLM is not a decoration on the cutscenes — it is a cognitive shim: the assistant that keeps a player oriented as case complexity grows. A player can use this feature many times, but some very bright players might get it right on the first go. This is what lets a mystery be as intricate as the real case demands without the player getting lost. The scripted narrative layer below is the delivery channel and the fallback; the LLM is the layer that scales comprehension. Section 9 is deferred in build order but primary in intent, so the model is shaped now to accommodate it (the generated step kind, the read-only context contract, and the authored case model).

Working agreement

  • All narrative content — campaigns, NPCs, poses, cutscenes, dialogue text — is authored template data frozen through supported operations. None of it is hard-coded into React components or SQL seed literals. The exception to this rule is custom cutscenes (react components) which are registered as components and referenced by the node.
  • The admin panel is a GUI over the same operations available to the manifest importer; both paths freeze the same immutable template data.
  • A cutscene never mutates a board. The professor's scene narrates the new document and goal; those exhibits and the updated brief already live in the next chapter's template.
  • A narrative behavior is complete only when its PostgreSQL representation, API behavior, frontend presentation, persistence, and focused tests agree.
  • Pose portraits are immutable shared bytes, stored and cloned exactly like document image assets (MinIO + objectStorage); scenes reference assets, they never duplicate them.

First vertical slice: "The Glass Harbour Diversion"

Build the smallest end-to-end narrative loop before generalizing. Ship these in order; each is playable on its own.

  • Add the splash screen — "PRINCIPAL INVESTIGATOR", Glitch University — with a single New Game action that creates a playthrough and launches the first scene (sections 1, 6, 7).
  • Create a mystery named The Glass Harbour Diversion as a one-chapter campaign wrapping the existing Glass Harbor level template (sections 12).
  • Add a briefing NPC (the Glitch University professor) and a mystery_intro cutscene that briefs the player, using at least two poses to prove pose-per-utterance (sections 23, 7).
  • Wire the briefing to play once on load and mark itself seen, then reveal the first level's board (sections 1, 6, 7).
  • Author two level_debrief end-scenes the player reaches by reporting back: one that sends them back to the board and one that concludes the mystery. Model these as two end-of-scene outcomes (buttons), not branching.
  • Leave the back-to-board scene as scripted for now, but author it as a generated-ready step (section 9) so the professor's hint can later be produced from the player's Case Report explanation.

1. Campaign / progression backbone

  • Define a cutscene node as something a) references a custom react component. That react can use potential utterances such that for example, it can play an ordered sequence utterance that brief the player: (speaker NPC, pose, text). A node can be marked has_utterances which permits the admin user to add utterances in order. [ ] A dialogue is another type of node that invokes the standard NPC dialogue component. This has utterances, and consist of a graph where utterances either are spoken by the NPC or available for selection. Example : if the NPC utters "Are you ready?" this has two child utterances marked "player" which could be "yes" and no. The user may select these. "No" could in principle point back to the same utterance and "yes" to the next. If an utterance has a non NULL terminal id, then the game advances to the node pointed to by that terminal. Available terminals are only those who have the current dialogue node as it parent.
  • There exists "det_gate" nodes and "llm_gate" nodes. We begin with the deterministic gate only. The end result of a level is sent to a "det_gate". The det gate can inspect the output of the level and determine if the story should advance through one of its terminals. For now, the det-gate always returns the happy path terminal leading to the mystery being solved.

2. NPC and pose catalog

  • Add an NPC entity (display name, short role e.g. "Glitch University professor", default pose) owned by the mystery/template family, so casts are authored rather than global magic strings.
  • Add poses as named portrait variants of an NPC (pose_key such as neutral, concerned, wry, pointing), each backed by one immutable image asset via the existing assets table + MinIO path.
  • Clone NPCs and pose→asset references (asset bytes reused, not copied) during template freeze and instantiation, mirroring document image cloning.
  • Enforce that every dialogue step names an NPC that exists in the mystery's cast; a missing pose is never an error.
  • Resolve a step's portrait at render time with graceful fallback: the requested pose_key, else the NPC's default pose, else no artwork (speaker name + text only). This lets authors add poses incrementally and keeps the first slice playable with zero uploaded art.

6. API contract

  • New Game / session: add POST …/playthroughs (create for the current user_id, per section 1) and GET …/playthroughs/current so the splash can offer New Game or Resume; scope every playthrough read/write to the caller's user_id so one player cannot touch another's game state.
  • Play mode: return a compact pendingCutscene payload (slot, ordered steps with resolved NPC name + pose asset URL) when one is due and unseen; add POST …/playthroughs/:id/cutscenes/:cutsceneId/seen (idempotent) and POST …/playthroughs/:id/advance implementing section 1's transactional advance.
  • Admin mode: add authenticated CRUD for mysteries, chapter ordering, NPCs and poses, and dialogue scenes/steps, plus the campaign freeze operation — all behind the existing admin JWT and edit=1 gate.
  • Keep authoring-only fields (raw pose keys, expected-solution data, unfrozen drafts) out of play-mode responses, consistent with how brief concept expectedPartyKind is already hidden in play mode.

Definition of done

A game designer can, in the admin panel, create a mystery, select existing levels as ordered chapters, create NPCs and upload named poses, craft dialogue scenes choosing a pose per step, and attach those scenes to chapter slots — then freeze it. A player lands on the "PRINCIPAL INVESTIGATOR" splash, chooses New Game to create a playthrough bound to their identity, watches the professor speak line-by-line with a changing portrait, investigates each board, reports back to advance a chapter that introduces a new document and goal, and reloads at any point without replaying seen scenes — with no dialogue text hard-coded in React and no cutscene mutating a board.