nexo-brain 1.5.1 → 1.5.3
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 +12 -0
- package/package.json +1 -1
- package/src/scripts/deep-sleep/__pycache__/analyze_session.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/__pycache__/apply_findings.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/__pycache__/collect_transcripts.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/apply_findings.py +70 -20
- package/src/scripts/nexo-deep-sleep.sh +21 -16
- package/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_cognitive.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_knowledge_graph.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_migrations.cpython-314-pytest-9.0.2.pyc +0 -0
package/README.md
CHANGED
|
@@ -130,10 +130,22 @@ Like a human brain, NEXO Brain has automated processes that run while you're not
|
|
|
130
130
|
|------|---------|---------------|
|
|
131
131
|
| 03:00 | Decay + memory consolidation + merge duplicates + dreaming | Deep sleep consolidation |
|
|
132
132
|
| 04:00 | Clean expired data, prune redundant memories | Synaptic pruning |
|
|
133
|
+
| 04:30 | **Deep Sleep** — analyze full session transcripts for uncaptured corrections, protocol violations, missed commitments | REM sleep review |
|
|
133
134
|
| 07:00 | Self-audit, health checks, metrics | Waking up + orientation |
|
|
134
135
|
| 23:30 | Process day's events, extract patterns | Pre-sleep reflection |
|
|
135
136
|
| Boot | Catch-up: run anything missed while computer was off | -- |
|
|
136
137
|
|
|
138
|
+
#### Deep Sleep (v1.5.2)
|
|
139
|
+
|
|
140
|
+
Deep Sleep reads your **complete session transcripts** (not just the diary summary) and finds what the agent missed during the day:
|
|
141
|
+
|
|
142
|
+
- **Uncaptured corrections** — user corrections the agent didn't save as learnings
|
|
143
|
+
- **Protocol violations** — guard_check skipped, trust not adjusted, change_log omitted
|
|
144
|
+
- **Missed commitments** — things mentioned but never tracked as followups
|
|
145
|
+
- **Quality issues** — agent declaring "done" when work wasn't complete
|
|
146
|
+
|
|
147
|
+
Uses Claude CLI in `--bare` mode (no hooks, no CLAUDE.md interference). Catch-up system re-runs yesterday if the Mac was off.
|
|
148
|
+
|
|
137
149
|
If your Mac was asleep during any scheduled process, NEXO Brain catches up in order when it wakes.
|
|
138
150
|
|
|
139
151
|
## Cognitive Cortex
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
5
|
"description": "NEXO — Cognitive co-operator for Claude Code. Atkinson-Shiffrin memory, semantic RAG, knowledge graph, HNSW vector indexing, trust scoring, and metacognitive error prevention.",
|
|
6
6
|
"bin": {
|
|
@@ -79,6 +79,44 @@ def adjust_trust(points: int, context: str):
|
|
|
79
79
|
pass
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def add_learning(category: str, title: str, content: str) -> bool:
|
|
83
|
+
"""Add a learning to nexo.db using real schema."""
|
|
84
|
+
if not NEXO_DB.exists():
|
|
85
|
+
return False
|
|
86
|
+
try:
|
|
87
|
+
now = datetime.now().timestamp()
|
|
88
|
+
conn = sqlite3.connect(str(NEXO_DB))
|
|
89
|
+
conn.execute(
|
|
90
|
+
"INSERT INTO learnings (category, title, content, created_at, updated_at, reasoning) VALUES (?, ?, ?, ?, ?, ?)",
|
|
91
|
+
(category, title, content, now, now, "Deep Sleep overnight analysis")
|
|
92
|
+
)
|
|
93
|
+
conn.commit()
|
|
94
|
+
conn.close()
|
|
95
|
+
return True
|
|
96
|
+
except Exception as e:
|
|
97
|
+
print(f" Error adding learning: {e}", file=sys.stderr)
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def add_followup(followup_id: str, description: str, date: str = None) -> bool:
|
|
102
|
+
"""Add a followup to nexo.db using real schema."""
|
|
103
|
+
if not NEXO_DB.exists():
|
|
104
|
+
return False
|
|
105
|
+
try:
|
|
106
|
+
now = datetime.now().timestamp()
|
|
107
|
+
conn = sqlite3.connect(str(NEXO_DB))
|
|
108
|
+
conn.execute(
|
|
109
|
+
"INSERT OR IGNORE INTO followups (id, description, date, status, created_at, updated_at, reasoning) VALUES (?, ?, ?, 'PENDIENTE', ?, ?, ?)",
|
|
110
|
+
(followup_id, description, date or "", now, now, "Deep Sleep overnight analysis")
|
|
111
|
+
)
|
|
112
|
+
conn.commit()
|
|
113
|
+
conn.close()
|
|
114
|
+
return True
|
|
115
|
+
except Exception as e:
|
|
116
|
+
print(f" Error adding followup: {e}", file=sys.stderr)
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
|
|
82
120
|
def apply(analysis: dict):
|
|
83
121
|
"""Apply all findings from deep sleep analysis."""
|
|
84
122
|
memory_dir = find_memory_dir()
|
|
@@ -88,32 +126,44 @@ def apply(analysis: dict):
|
|
|
88
126
|
|
|
89
127
|
print(f"\nApplying findings for {date}...")
|
|
90
128
|
|
|
91
|
-
# 1. Uncaptured corrections → feedback memories
|
|
129
|
+
# 1. Uncaptured corrections → learnings + feedback memories
|
|
92
130
|
for i, correction in enumerate(analysis.get("uncaptured_corrections", [])):
|
|
93
131
|
severity = correction.get("severity", "medium")
|
|
94
|
-
if severity not in ("high", "critical"):
|
|
95
|
-
continue
|
|
96
|
-
|
|
97
132
|
category = correction.get("category", "process")
|
|
98
133
|
content = correction.get("what_nexo_should_have_saved", "")
|
|
99
134
|
quote = correction.get("quote", "")
|
|
100
135
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
# All corrections → learnings
|
|
137
|
+
learning_title = f"[Deep Sleep] {content[:80]}"
|
|
138
|
+
learning_content = f"User said: \"{quote}\"\nContext: {correction.get('context', '')}\nRepeated: {correction.get('times_repeated', 1)} times"
|
|
139
|
+
if add_learning(category, learning_title, learning_content):
|
|
140
|
+
actions_taken.append(f"learning_add: {learning_title[:50]}")
|
|
141
|
+
|
|
142
|
+
# High/critical → also feedback memories
|
|
143
|
+
if severity in ("high", "critical"):
|
|
144
|
+
safe_name = category.replace(" ", "_").lower()
|
|
145
|
+
filename = f"ds_{date}_{safe_name}_{i}.md"
|
|
146
|
+
write_feedback_memory(
|
|
147
|
+
memory_dir, filename,
|
|
148
|
+
name=content[:60],
|
|
149
|
+
description=f"Deep sleep detected uncaptured correction ({severity})",
|
|
150
|
+
content=f"{content}\n\n**Why:** User said: \"{quote}\"\nContext: {correction.get('context', '')}\n\n**How to apply:** {content}"
|
|
151
|
+
)
|
|
152
|
+
memory_entries.append({
|
|
153
|
+
"title": content[:40],
|
|
154
|
+
"filename": filename,
|
|
155
|
+
"summary": f"Deep sleep {date}, severity {severity}"
|
|
156
|
+
})
|
|
157
|
+
actions_taken.append(f"feedback_write: {filename}")
|
|
158
|
+
|
|
159
|
+
# 2. Missed commitments → followups
|
|
160
|
+
for i, commitment in enumerate(analysis.get("missed_commitments", [])):
|
|
161
|
+
fid = f"NF-DS-{date}-{i}"
|
|
162
|
+
desc = f"[Deep Sleep] {commitment.get('commitment', '')[:100]}"
|
|
163
|
+
if add_followup(fid, desc, commitment.get("due_date")):
|
|
164
|
+
actions_taken.append(f"followup: {desc[:50]}")
|
|
165
|
+
|
|
166
|
+
# 3. Trust adjustments for critical violations
|
|
117
167
|
critical_violations = [v for v in analysis.get("protocol_violations", []) if v.get("severity") == "critical"]
|
|
118
168
|
if critical_violations:
|
|
119
169
|
points = -3 * len(critical_violations)
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# NEXO Deep Sleep — Complete overnight session
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# NEXO Deep Sleep — Complete overnight session analysis
|
|
3
|
+
# Runs at 4:30 AM via LaunchAgent
|
|
4
|
+
# Reads ALL session transcripts from the day, analyzes with Claude CLI,
|
|
5
|
+
# and applies findings (learnings, feedbacks, followups, trust adjustments)
|
|
5
6
|
#
|
|
6
7
|
# Features:
|
|
7
8
|
# - Catch-up: if yesterday was missed (Mac off/asleep), runs it first
|
|
8
|
-
# -
|
|
9
|
-
# -
|
|
10
|
-
#
|
|
11
|
-
# Install: Add as LaunchAgent for daily execution (recommended: 4:30 AM)
|
|
9
|
+
# - Logs to ~/claude/logs/deep-sleep.log
|
|
10
|
+
# - Marks completion in .last-run for watchdog monitoring
|
|
12
11
|
|
|
13
12
|
set -euo pipefail
|
|
14
13
|
|
|
@@ -26,9 +25,11 @@ run_analysis() {
|
|
|
26
25
|
local DATE="$1"
|
|
27
26
|
log "=== Deep Sleep starting for $DATE ==="
|
|
28
27
|
|
|
28
|
+
# Step 1: Collect transcripts
|
|
29
29
|
log "Step 1: Collecting transcripts for $DATE..."
|
|
30
30
|
python3 "$SCRIPT_DIR/deep-sleep/collect_transcripts.py" "$DATE" 2>&1 | tee -a "$LOG_DIR/deep-sleep.log"
|
|
31
31
|
|
|
32
|
+
# Check if transcripts were found
|
|
32
33
|
if [ ! -f "$DEEP_SLEEP_DIR/$DATE-transcripts.json" ]; then
|
|
33
34
|
log "No transcripts file generated for $DATE. Skipping."
|
|
34
35
|
return 0
|
|
@@ -40,6 +41,7 @@ run_analysis() {
|
|
|
40
41
|
return 0
|
|
41
42
|
fi
|
|
42
43
|
|
|
44
|
+
# Step 2: Analyze with Claude CLI
|
|
43
45
|
log "Step 2: Analyzing $SESSIONS sessions with Claude CLI..."
|
|
44
46
|
python3 "$SCRIPT_DIR/deep-sleep/analyze_session.py" "$DATE" 2>&1 | tee -a "$LOG_DIR/deep-sleep.log"
|
|
45
47
|
|
|
@@ -48,6 +50,7 @@ run_analysis() {
|
|
|
48
50
|
return 1
|
|
49
51
|
fi
|
|
50
52
|
|
|
53
|
+
# Step 3: Apply findings
|
|
51
54
|
log "Step 3: Applying findings for $DATE..."
|
|
52
55
|
python3 "$SCRIPT_DIR/deep-sleep/apply_findings.py" "$DATE" 2>&1 | tee -a "$LOG_DIR/deep-sleep.log"
|
|
53
56
|
|
|
@@ -55,22 +58,24 @@ run_analysis() {
|
|
|
55
58
|
return 0
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
# --- Catch-up: check if yesterday was missed ---
|
|
61
|
+
# --- Catch-up: check if the day before yesterday was missed ---
|
|
59
62
|
YESTERDAY=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d "yesterday" +%Y-%m-%d 2>/dev/null)
|
|
63
|
+
DAY_BEFORE=$(date -v-2d +%Y-%m-%d 2>/dev/null || date -d "2 days ago" +%Y-%m-%d 2>/dev/null)
|
|
60
64
|
LAST_RUN=""
|
|
61
65
|
if [ -f "$LAST_RUN_FILE" ]; then
|
|
62
66
|
LAST_RUN=$(cat "$LAST_RUN_FILE")
|
|
63
67
|
fi
|
|
64
68
|
|
|
65
|
-
if [ -n "$
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
if [ -n "$DAY_BEFORE" ] && [ "$LAST_RUN" != "$DAY_BEFORE" ] && [ "$LAST_RUN" != "$YESTERDAY" ]; then
|
|
70
|
+
# Day before yesterday wasn't analyzed — catch up
|
|
71
|
+
if [ ! -f "$DEEP_SLEEP_DIR/$DAY_BEFORE-analysis.json" ]; then
|
|
72
|
+
log "*** CATCH-UP: $DAY_BEFORE was missed. Running now. ***"
|
|
73
|
+
run_analysis "$DAY_BEFORE" || log "Catch-up for $DAY_BEFORE failed."
|
|
69
74
|
fi
|
|
70
75
|
fi
|
|
71
76
|
|
|
72
|
-
# --- Run
|
|
73
|
-
run_analysis "$
|
|
77
|
+
# --- Run yesterday's analysis (main task — at 4:30 AM, today has no sessions yet) ---
|
|
78
|
+
run_analysis "$YESTERDAY"
|
|
74
79
|
|
|
75
|
-
# Mark completion
|
|
76
|
-
echo "$
|
|
80
|
+
# Mark completion with yesterday's date (what we actually analyzed)
|
|
81
|
+
echo "$YESTERDAY" > "$LAST_RUN_FILE"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|