loki-mode 7.5.14 → 7.5.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/memory/storage.py CHANGED
@@ -329,22 +329,50 @@ class MemoryStorage:
329
329
  """
330
330
  Load JSON data from a file.
331
331
 
332
+ Per-file resilience (Triage #15): a single corrupt, unreadable, or
333
+ non-UTF8 file must NOT propagate an exception to callers iterating
334
+ over many files (e.g. ``.loki/memory/episodic/*.json``). On any
335
+ load failure we log a warning and return None so the caller can
336
+ skip and continue.
337
+
332
338
  Args:
333
339
  path: Path to JSON file
334
340
 
335
341
  Returns:
336
- Parsed JSON as dictionary, or None if file doesn't exist or is corrupted
342
+ Parsed JSON as dictionary, or None if file doesn't exist,
343
+ is unreadable, contains invalid JSON, or is not UTF-8.
337
344
  """
338
345
  path = Path(path)
339
346
  if not path.exists():
340
347
  return None
341
348
 
342
- with self._file_lock(path, exclusive=False):
343
- with open(path, "r") as f:
344
- try:
345
- return json.load(f)
346
- except json.JSONDecodeError:
347
- return None
349
+ try:
350
+ with self._file_lock(path, exclusive=False):
351
+ with open(path, "r", encoding="utf-8") as f:
352
+ try:
353
+ return json.load(f)
354
+ except json.JSONDecodeError as exc:
355
+ import logging
356
+ logging.getLogger(__name__).warning(
357
+ "Skipping corrupt JSON file %s: %s", path, exc
358
+ )
359
+ return None
360
+ except UnicodeDecodeError as exc:
361
+ import logging
362
+ logging.getLogger(__name__).warning(
363
+ "Skipping non-UTF8 JSON file %s: %s", path, exc
364
+ )
365
+ return None
366
+ except (OSError, UnicodeDecodeError) as exc:
367
+ # OSError covers I/O errors, permission errors, and missing
368
+ # files that race with the existence check above.
369
+ # UnicodeDecodeError can also surface from the file_lock /
370
+ # open layer on some platforms.
371
+ import logging
372
+ logging.getLogger(__name__).warning(
373
+ "Skipping unreadable JSON file %s: %s", path, exc
374
+ )
375
+ return None
348
376
 
349
377
  def _generate_id(self, prefix: str) -> str:
350
378
  """
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "7.5.14",
3
+ "version": "7.5.16",
4
4
  "description": "Loki Mode by Autonomi. Multi-agent autonomous SDLC framework. Spec to deployed app: PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief. 5 AI providers (Claude Code, OpenAI Codex, Google Gemini, Cline, Aider). 11 quality gates.",
5
5
  "keywords": [
6
6
  "agent",