Backend:
- provider: fall back to parsing a plain JSON body when a server ignores
stream=true (was: silent empty turn); error if response has no text (#5)
- memorybank: clamp cursors after undo/retry shrinks the action list, and
translate summary_cursor (list position) to an Action.index boundary
before comparing with Memory.source_end (#7)
- memorybank: pinned memories now count toward the top_k budget (#8)
- memorybank: cosine() returns 0.0 on dimension mismatch; changing the
embedding model clears stored vectors so they re-embed (#9)
- scripting: MAX_STORY_CARDS cap now counts cards inserted during the
hook, so a script can't add unbounded cards in one turn (#10)
- settings: /test tolerates non-dict JSON from /models (#13)
- scenarios: import accepts worldInformation as a story-card source (#14)
Frontend:
- per-key debounce timers in PlotPanel and ScenarioEditor — editing two
things within 600ms no longer drops the first save (#15, #16)
- Continue button no longer discards typed input (#17)
- failed retry resyncs actions from the server instead of leaving the
removed action missing (#18)
- Settings save/test surface errors instead of hanging on Testing… (#19)
- InsightsPanel ignores stale responses from superseded requests (#20)
- placeholder scan includes story-card trigger keys (#21)
addStoryCard returning the 0-based index (falsy for the first card) matches
real AI Dungeon per the scripting guidebook — kept, documented (#11).
Statuses updated in CODE_REVIEW_FINDINGS.md; stale entries for previously
fixed items (#1-4, #6, #12) corrected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFsGHju9szibJJa2YJcdbg