- SessionLogger listens for a new LogEntry bus event; dice rolls,
initiative turns/rounds, generated encounters and calendar day
advances land in the active session as timestamped entries — the
raw material the AI summary actually needs. Mute toggle in the
toolbar (persisted, default on).
- NPC Generator: '⚔ to initiative' button pushes the generated stat
block (HP) into the tracker via the existing AddCombatants bus event.
- ragQuery now set on Encounter, Quest and Session summary too
(NPC/Item/World already had it) — every generator is world-grounded.
- Created shared lib/llm-parse.ts with extractJson(), parseLlmJson(),
flattenValue(), and ensureArray() utilities
- Strips markdown code fences (\`\`\`json ... \`\`\`) before parsing
- Handles nested objects where strings were expected (flattens them)
- Handles arrays that come back as strings or objects
- Updated all AI prompts to explicitly request raw JSON with no fences
- All 5 AI components now use parseLlmJson() instead of raw regex
- ItemForge shows raw LLM response in expandable <details> when parsing fails
- Added 'IMPORTANT: Return ONLY raw JSON' instruction to all prompts
- Full production build passing