diff --git a/skills/cognitive-memory/client.py b/skills/cognitive-memory/client.py index a4636c1..a30b6ff 100644 --- a/skills/cognitive-memory/client.py +++ b/skills/cognitive-memory/client.py @@ -622,9 +622,30 @@ class CognitiveMemoryClient: return {"version": 1, "updated": "", "entries": {}} def _save_state(self, state: Dict): - """Write _state.json.""" + """Write _state.json atomically, merging top-level keys to prevent race conditions.""" + import tempfile + + # Merge with existing state to preserve keys written by concurrent processes + if self.state_path.exists(): + try: + existing = json.loads(self.state_path.read_text()) + existing.update(state) + state = existing + except (json.JSONDecodeError, OSError): + pass state["updated"] = datetime.now(timezone.utc).isoformat() - self.state_path.write_text(json.dumps(state, indent=2, default=str)) + # Atomic write: write to temp file then rename + fd, tmp_path = tempfile.mkstemp(dir=self.memory_dir, suffix=".tmp") + try: + with os.fdopen(fd, "w") as f: + json.dump(state, f, indent=2, default=str) + os.replace(tmp_path, self.state_path) + except Exception: + try: + os.unlink(tmp_path) + except OSError: + pass + raise # ------------------------------------------------------------------------- # File I/O