- chat:ledger becomes the only conversation store: model messages land as
user/tool_call(payload)/tool_result/ai events via EventLogChatMemory
(per-event rightPush, no more whole-blob read-modify-write races)
- EventProjectionService: one renderer for both frontend history and LLM
context (system+flow card / deterministic digest of expired turns /
~6000-char verbatim recent turns, current turn payload-exact)
- pinned active-flow card (form pending / proposal pending / skill_active
full text) unpinned on executed/cancelled/skill_done
- anti-fab retry nudges logged as internal user events (LLM-visible,
hidden from history); grounded suffixes never duplicate user events
- delete ProjectedChatMemory; RedisChatMemoryStore demoted to legacy
read-only compat (old convs age out via 30d TTL); conv list lazy cleanup
- tests: projection correctness + concurrent stream/confirm append safety