A save file is untrusted input
parseParty rebuilds the world from createWorld and overlays only recognised fields, clamped, with every id checked against the room's own cast, locations, masks and actions. A hand-edited file may make a strange party but never a broken one.
A save file is a document a stranger can write. Treating it as a state object to be assigned is how a toy acquires a crash, or worse, an id that points somewhere the engine assumed it could not.
Rebuild, then overlay
The reader never hydrates the incoming object. It calls createWorld for the room, producing a world that is valid by construction, and then copies in only the fields it recognises: numbers clamped to their ranges, ids checked against the room's own cast, locations, masks and action menu, references dropped instead of trusted.
Anything unknown is discarded. Anything out of range is clamped rather than rejected, because the goal is a playable party and refusing a file for a trust value of 1.3 helps nobody.
Strange is fine, broken is not
A hand-edited file that gives everybody maximum standing is a legitimate thing to want, and it plays. A file naming a guest who does not exist in that room never reaches the engine at all.
There is a test that edits a file on purpose. It is the only real way to be sure the reader is still a reader and has not become an assignment.
The general rule
Any state you let a user hand back to you is input, no matter that you wrote it five minutes earlier. Build the valid object yourself and let the document influence it. Never let the document be it.
Read next
Saving a party as one file
Save writes the whole night, full world state plus every ticker line with timestamps, as a single JSON document that reads as a transcript in any editor. Resume picks the night back up at exactly that beat.
coerce(): when the code overrules the model
coerce() is the last word on every decision. It drops forbidden actions, enforces gates and confidence floors, refuses moves the character cannot afford, and puts every override on screen in amber.
One party in memory, streamed to everyone
A room is a single party held in server memory and streamed to every watcher, so everybody sees the same betrayal at the same moment and the model is paid for once per beat however many people are looking.