nexo-brain 5.3.27 → 5.3.28
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/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/src/hook_guardrails.py +44 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.28",
|
|
4
4
|
"description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "NEXO Brain",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.28",
|
|
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/hook_guardrails.py
CHANGED
|
@@ -225,6 +225,23 @@ def _session_has_guard_check(conn, sid: str) -> bool:
|
|
|
225
225
|
return bool(row)
|
|
226
226
|
|
|
227
227
|
|
|
228
|
+
def _session_has_guard_for_file(conn, sid: str, filepath: str) -> bool:
|
|
229
|
+
"""Check if guard_check was called for a specific file in this session."""
|
|
230
|
+
if not filepath:
|
|
231
|
+
return False
|
|
232
|
+
normalized = _normalize_file_path(filepath)
|
|
233
|
+
basename = os.path.basename(filepath)
|
|
234
|
+
# guard_checks.files is a comma-separated or JSON list of paths/areas
|
|
235
|
+
row = conn.execute(
|
|
236
|
+
"""SELECT 1 FROM guard_checks
|
|
237
|
+
WHERE session_id = ?
|
|
238
|
+
AND (files LIKE ? OR files LIKE ? OR files LIKE ?)
|
|
239
|
+
LIMIT 1""",
|
|
240
|
+
(sid, f"%{normalized}%", f"%{basename}%", f"%{filepath}%"),
|
|
241
|
+
).fetchone()
|
|
242
|
+
return bool(row)
|
|
243
|
+
|
|
244
|
+
|
|
228
245
|
def _find_open_debt(conn, *, session_id: str, task_id: str, debt_type: str, file_token: str) -> dict | None:
|
|
229
246
|
row = conn.execute(
|
|
230
247
|
"""SELECT *
|
|
@@ -548,6 +565,28 @@ def process_pre_tool_event(payload: dict) -> dict:
|
|
|
548
565
|
"reason_code": "guard_unacknowledged",
|
|
549
566
|
}
|
|
550
567
|
)
|
|
568
|
+
continue
|
|
569
|
+
|
|
570
|
+
# Check if guard_check was called for this specific file
|
|
571
|
+
if not _session_has_guard_for_file(conn, sid, filepath):
|
|
572
|
+
debt = _ensure_protocol_debt(
|
|
573
|
+
conn,
|
|
574
|
+
session_id=sid,
|
|
575
|
+
task_id=task["task_id"],
|
|
576
|
+
debt_type="write_without_file_guard_check",
|
|
577
|
+
severity="warn",
|
|
578
|
+
evidence=f"{tool_name} attempted on {filepath} without a prior guard_check covering that file.",
|
|
579
|
+
file_token=filepath,
|
|
580
|
+
)
|
|
581
|
+
blocks.append(
|
|
582
|
+
{
|
|
583
|
+
"file": filepath,
|
|
584
|
+
"task_id": task["task_id"],
|
|
585
|
+
"debt_id": debt.get("id"),
|
|
586
|
+
"debt_type": "write_without_file_guard_check",
|
|
587
|
+
"reason_code": "missing_file_guard",
|
|
588
|
+
}
|
|
589
|
+
)
|
|
551
590
|
|
|
552
591
|
return {
|
|
553
592
|
"ok": True,
|
|
@@ -728,6 +767,11 @@ def format_pretool_block_message(result: dict) -> str:
|
|
|
728
767
|
lines.append(
|
|
729
768
|
f"- {file_note}: task {item['task_id']} still has blocking guard debt. Acknowledge it with `nexo_task_acknowledge_guard` before retrying."
|
|
730
769
|
)
|
|
770
|
+
elif item.get("reason_code") == "missing_file_guard":
|
|
771
|
+
lines.append(
|
|
772
|
+
f"- {file_note}: `nexo_guard_check` obligatorio antes de editar. "
|
|
773
|
+
f"Run `nexo_guard_check(files='{file_note}')` first, then retry the edit."
|
|
774
|
+
)
|
|
731
775
|
elif strictness == "learning":
|
|
732
776
|
lines.append(
|
|
733
777
|
f"- {file_note}: open `nexo_task_open(task_type='edit', files=['{file_note}'])` first, then rerun the edit."
|