nexo-brain 7.20.16 → 7.20.17
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/README.md +3 -1
- package/package.json +1 -1
- package/src/db_guard.py +16 -1
package/README.md
CHANGED
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
[Watch the overview video](https://nexo-brain.com/watch/) · [Watch on YouTube](https://www.youtube.com/watch?v=i2lkGhKyVqI) · [Open the infographic](https://nexo-brain.com/assets/nexo-brain-infographic-v5.png)
|
|
20
20
|
|
|
21
|
-
Version `7.20.
|
|
21
|
+
Version `7.20.17` is the current packaged-runtime line. Patch release over v7.20.16 — validated DB backups now tolerate tiny live-write growth from the Local Memory indexer while still rejecting real protected-table loss.
|
|
22
|
+
|
|
23
|
+
Previously in `7.20.16`: patch release over v7.20.15 — packaged updates keep the `local_context` runtime shim importable and rollback code-tree snapshots safely when compatibility directories are symlinks.
|
|
22
24
|
|
|
23
25
|
Previously in `7.20.15`: patch release over v7.20.14 — Brain update/recovery paths now fail closed when the DB guard is missing or stale, and backup validation rejects any replacement that loses Local Memory tables.
|
|
24
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.20.
|
|
3
|
+
"version": "7.20.17",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
5
|
"description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
|
|
6
6
|
"homepage": "https://nexo-brain.com",
|
package/src/db_guard.py
CHANGED
|
@@ -455,13 +455,28 @@ def validate_backup_matches_source(
|
|
|
455
455
|
if s is not None and d is None:
|
|
456
456
|
discrepancies.append(f"{table}: source={s} backup=missing")
|
|
457
457
|
continue
|
|
458
|
-
if s is not None and d is not None and d < s:
|
|
458
|
+
if s is not None and d is not None and d < s and not _backup_drift_is_safe(s, d):
|
|
459
459
|
discrepancies.append(f"{table}: source={s} backup={d}")
|
|
460
460
|
if discrepancies:
|
|
461
461
|
return False, "; ".join(discrepancies)
|
|
462
462
|
return True, None
|
|
463
463
|
|
|
464
464
|
|
|
465
|
+
def _backup_drift_is_safe(source_count: int, backup_count: int) -> bool:
|
|
466
|
+
"""Allow tiny live-write drift while still rejecting real backup data loss.
|
|
467
|
+
|
|
468
|
+
`sqlite3.backup()` creates a consistent snapshot, but NEXO's background
|
|
469
|
+
memory service can add rows immediately after the snapshot. Comparing the
|
|
470
|
+
backup with the live DB after that growth must not abort an update. Small
|
|
471
|
+
tables stay exact because a 1-row loss there can be meaningful.
|
|
472
|
+
"""
|
|
473
|
+
if backup_count <= 0 or source_count < 1000:
|
|
474
|
+
return False
|
|
475
|
+
drift = source_count - backup_count
|
|
476
|
+
allowed = max(25, int(source_count * 0.005))
|
|
477
|
+
return 0 < drift <= allowed
|
|
478
|
+
|
|
479
|
+
|
|
465
480
|
def _quote_identifier(identifier: str) -> str:
|
|
466
481
|
if identifier not in PROTECTED_TABLES:
|
|
467
482
|
raise ValueError(f"refusing unsafe table identifier: {identifier!r}")
|