From 8c06fd1be707ddca2ac2f0467defb4629c813108 Mon Sep 17 00:00:00 2001 From: Dejvino Date: Thu, 25 Jun 2026 19:31:58 +0200 Subject: [PATCH] reject character/world updates that are <70% of original size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds _validate_update_size() safeguard that skips writing if the LLM returns a fragment instead of the full file — warns on stderr. --- tools/engine.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tools/engine.py b/tools/engine.py index 61a7658..e4642d2 100644 --- a/tools/engine.py +++ b/tools/engine.py @@ -636,8 +636,6 @@ class GameEngine: if finalize_call: args = finalize_call.get("args", {}) errs = [] - if not args.get("dm_status"): - errs.append("dm_status is required") if not args.get("book_log"): errs.append("book_log is required") if not args.get("user_prompt"): @@ -767,13 +765,36 @@ class GameEngine: # ── State Persistence ─────────────────────────────────────────────── + def _validate_update_size(self, name: str, new_content: str, path: Path) -> bool: + """Reject updates that are more than 30% shorter than the existing file + — likely the LLM pasted a fragment instead of the full state.""" + if not path.exists(): + return True + old = path.read_text().strip() + if not old: + return True + ratio = len(new_content) / len(old) + if ratio < 0.7: + import sys + print( + f"WARNING: {name} update rejected ({ratio:.0%} of original size " + f"= {len(new_content)} vs {len(old)} chars) — likely a partial paste.", + file=sys.stderr, + ) + return False + return True + def apply_state(self, result: TurnResult) -> None: """Write state changes from a TurnResult to disk.""" - if result.character_updates: + if result.character_updates and self._validate_update_size( + "character", result.character_updates, CHAR_PATH + ): CHAR_PATH.write_text(result.character_updates.strip() + "\n") - if result.world_updates: + if result.world_updates and self._validate_update_size( + "world", result.world_updates, WORLD_PATH + ): WORLD_PATH.write_text(result.world_updates.strip() + "\n") if result.ambience: