A 5e storytelling engine with an LLM DM

Harden the chat client, width math, campaign files, and SRD fetch master

The full-repo review found defects that bite in real play, and this lands the four independent fixes together. The chat client now keys tool-call fragments on id with the index as a hint, so providers that reuse index 0 or interleave calls assemble correctly; it sets connect, response, and body timeouts so a dead connection frees the worker; it retries 429 and 5xx up to twice before the first delta; and the SSE reader goes quiet for good after [DONE]. Wrapping, tables, the editor, and the prompt measure display columns and break on grapheme clusters, so emoji and CJK no longer overflow rows that scrollback can never repaint. The campaign clock walks day files newest-first for its anchor, so a truncated file cannot rewind it; only a valid game time opens a transcript section, so a markdown heading in narration is just text; transcript appends only add bytes; and a failed campaign write now surfaces to the player instead of vanishing. SRD fetch refuses to overwrite a vendored tree whose pin does not match, preserving the 21 hand-patched files and their meta.yaml record, and the fidelity diff caps its alignment matrix at 32 MB instead of allocating gigabytes on a mistyped source field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>