Add authorable per-level briefing checklist

The case briefing showed a wall of body text. Add a checklist of short,
player-tickable steps authored per level: a new `checklist` on the level brief
(table osint.level_brief_checklist_items), read/written with the board, cloned
on template freeze/instantiate, and carried through the mystery importer and the
mystery:pull exporter. Player tick state is guidance-only, persisted locally per
level rather than on the shared board. Convert the Barricelli inventor-proof
brief from prose into a short intro plus a six-step checklist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 22:50:50 +02:00
co-authored by Claude Opus 4.8
parent 95b17e945c
commit e37dc651f3
9 changed files with 53 additions and 12 deletions
+2 -2
View File
@@ -45,7 +45,7 @@ type MysteryLevel = {
title: string
subtitle?: string
timelineRange?: { start: string; end: string }
brief?: { body: string; concepts: { label: string; context: string; expectedPartyKind: PartyKind }[] }
brief?: { body: string; concepts?: { label: string; context: string; expectedPartyKind: PartyKind }[]; checklist?: string[] }
documents?: MysteryDocument[]
folders?: { key: string; title: string; content: string; x: number; y: number; width: number; members: string[] }[]
claims?: { key:string;statement:string;x:number;y:number;width?:number;height?:number }[]
@@ -116,7 +116,7 @@ async function importLevel(baseUrl: string, folderDir: string, level: MysteryLev
}
const folderIds = new Map(levelFolders.map(folder => [folder.key, randomUUID()]))
if (level.brief) state.brief = { body: level.brief.body, concepts: level.brief.concepts.map(concept => ({ id: randomUUID(), ...concept })) }
if (level.brief) state.brief = { body: level.brief.body, concepts: (level.brief.concepts || []).map(concept => ({ id: randomUUID(), ...concept })), checklist: level.brief.checklist }
state.views = state.views.map(view => view.type === 'timeline' ? { ...view, rangeMode: level.timelineRange ? 'fixed' : 'auto', range: level.timelineRange } : view)
const folders = levelFolders.map(folder => ({
id: folderIds.get(folder.key)!, type: 'folder', title: folder.title, content: folder.content,