Skip to content

Keep changes made at the same time by the app, AI assistants and phones - #70

Merged
mLampir merged 6 commits into
mainfrom
claude/project-thread-830rjm-sync
Oct 19, 2026
Merged

mLampir merged 6 commits into
mainfrom
claude/project-thread-830rjm-sync

Conversation

@mLampir

@mLampir mLampir commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

What changes

Before: a save replaced the adventure or the parties without looking at what changed meanwhile. An AI change made while the game master was typing could be overwritten by the next autosave, or the last edits typed before the AI change were dropped; a phone sign-up and a party edit could overwrite each other.

After:

  • Server: adventures, the parties and the monsters each have a revision. GET sends it as ETag; a PUT with If-Match based on an older version gets 412 with the current version. PUT without If-Match works as before.
  • AI assistants (MCP): a change to an adventure that changed meanwhile is applied again to the new version, up to four times. list_adventures reads only the list instead of every adventure.
  • Game master app: pending edits are saved before a change from elsewhere is loaded. On a conflict the app combines both sides field by field and entry by entry; only where both changed the same field the other side wins and a notice says so. A party save that meets a phone sign-up takes the sign-up in and saves again.
  • Faster server: parsed adventure, session and library files are cached by modification time and size, so a save no longer reads every adventure in the folder. Images for the phones are decoded once per reveal.

Checklist

  • pnpm lint, pnpm typecheck and pnpm test pass
  • New user-facing text has English and German strings
  • No protected content, personal data or API keys

🤖 Generated with Claude Code

mLampir and others added 5 commits October 13, 2026 05:19
Every adventure file, the party library and the monster library now
have a revision, a hash of the file's text. GET answers it as ETag;
PUT accepts If-Match and answers 412 with the current version and its
ETag when the file changed since, so an AI change, a phone sign-up and
an edit in another tab no longer overwrite each other unseen. PUT
without If-Match replaces as before, for imports and older clients.
A successful PUT answers the new ETag.

The store kept reading and checking every adventure file for every
list, get and save, every session file for the current session and the
party library for every phone poll. It now keeps parsed files by path
and reads one again only when its time or size changed, and forgets a
file it wrote itself. Broken files and files from a newer version are
still listed as before.

The adventure list also names each adventure's party, so the MCP
server can list adventures without reading every one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every phone asked for a shown image and the server decoded its data
address each time, byte by byte through atob. It now decodes it with
Node's base64 decoder once and keeps the bytes while the reveal shows
the same image.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The MCP tools read an adventure, change it and save it. An edit the
game master saved in between was overwritten. The save now sends the
version it was based on; when the server refuses it, the change is
applied to the newer version and saved again, up to four times. An
adventure that keeps changing is not saved, and the assistant is told
to call the tool again.

list_adventures read every adventure in full through the server; it
now uses the server's list, which names the party too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The app saved an adventure shortly after every change and replaced it
with the newer version when an AI assistant or another tab changed it.
A stale autosave could overwrite the other change, and a reload dropped
what was typed in the last moment.

The app now keeps the ETag of the version it shows and sends it with
every save. When a notice says the adventure changed, pending edits are
saved first. When the server answers that a newer version was saved
meanwhile, the edits made here are combined with it field by field, and
lists of scenes, NPCs and other entries entry by entry, then saved on
top of it. Only where both sides changed the same field does the other
change win; a short notice above the editor then asks the game master
to check the last edit. This keeps both sides in the common case, where
the assistant and the game master work on different things, without a
dialog in the way.

A party saved from an older list, e.g. while a player entered a
character on their phone, now takes the characters from the phones in
and is saved again instead of dropping them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mLampir mLampir self-assigned this Oct 13, 2026
@mLampir
mLampir marked this pull request as ready for review October 19, 2026 08:27
Base automatically changed from claude/project-thread-830rjm to main October 19, 2026 08:28
…d-830rjm-sync

# Conflicts:
#	packages/server/src/server.ts
@mLampir
mLampir merged commit 627d8bb into main Oct 19, 2026
3 checks passed
@mLampir
mLampir deleted the claude/project-thread-830rjm-sync branch October 19, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant