nexo-brain 5.3.19 → 5.3.21
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/bin/nexo-brain.js +52 -10
- package/package.json +1 -1
- package/src/auto_update.py +11 -8
- package/src/dashboard/static/favicon 2.svg +32 -0
- package/src/dashboard/static/nexo-logo 2.png +0 -0
- package/src/dashboard/static/nexo-logo 2.svg +40 -0
- package/src/dashboard/static/style 2.css +2458 -0
- package/src/dashboard/templates/adaptive 2.html +118 -0
- package/src/dashboard/templates/artifacts 2.html +133 -0
- package/src/dashboard/templates/backups 2.html +136 -0
- package/src/dashboard/templates/base 2.html +417 -0
- package/src/dashboard/templates/calendar 2.html +591 -0
- package/src/dashboard/templates/chat 2.html +356 -0
- package/src/dashboard/templates/claims 2.html +259 -0
- package/src/dashboard/templates/cortex 2.html +321 -0
- package/src/dashboard/templates/credentials 2.html +128 -0
- package/src/dashboard/templates/crons 2.html +370 -0
- package/src/dashboard/templates/dashboard 2.html +494 -0
- package/src/dashboard/templates/dreams 2.html +252 -0
- package/src/dashboard/templates/email 2.html +160 -0
- package/src/dashboard/templates/evolution 2.html +189 -0
- package/src/dashboard/templates/feed 2.html +249 -0
- package/src/dashboard/templates/followup_health 2.html +170 -0
- package/src/dashboard/templates/graph 2.html +201 -0
- package/src/dashboard/templates/guard 2.html +259 -0
- package/src/dashboard/templates/inbox 2.html +251 -0
- package/src/dashboard/templates/memory 2.html +420 -0
- package/src/dashboard/templates/operations 2.html +608 -0
- package/src/dashboard/templates/plugins 2.html +185 -0
- package/src/dashboard/templates/protocol 2.html +199 -0
- package/src/dashboard/templates/rules 2.html +246 -0
- package/src/dashboard/templates/sentiment 2.html +247 -0
- package/src/dashboard/templates/sessions 2.html +218 -0
- package/src/dashboard/templates/skills 2.html +329 -0
- package/src/dashboard/templates/somatic 2.html +73 -0
- package/src/dashboard/templates/triggers 2.html +133 -0
- package/src/dashboard/templates/trust 2.html +360 -0
- package/src/db/__init__ 2.py +259 -0
- package/src/db/_core 2.py +437 -0
- package/src/db/_credentials 2.py +124 -0
- package/src/db/_episodic 2.py +762 -0
- package/src/db/_evolution 2.py +54 -0
- package/src/db/_fts 2.py +406 -0
- package/src/db/_goal_profiles 2.py +376 -0
- package/src/db/_hot_context 2.py +660 -0
- package/src/db/_outcomes 2.py +800 -0
- package/src/db/_personal_scripts 2.py +582 -0
- package/src/db/_sessions 2.py +330 -0
- package/src/db/_tasks 2.py +91 -0
- package/src/db/_watchers 2.py +173 -0
- package/src/doctor/formatters 2.py +52 -0
- package/src/doctor/models 2.py +69 -0
- package/src/doctor/planes 2.py +87 -0
- package/src/doctor/providers/__init__ 2.py +1 -0
- package/src/doctor/providers/deep 2.py +367 -0
- package/src/evolution_cycle 2.py +519 -0
- package/src/hooks/auto_capture 2.py +208 -0
- package/src/hooks/caffeinate-guard 2.sh +8 -0
- package/src/hooks/capture-session 2.sh +21 -0
- package/src/hooks/capture-tool-logs 2.sh +158 -0
- package/src/hooks/daily-briefing-check 2.sh +33 -0
- package/src/hooks/heartbeat-enforcement 2.py +90 -0
- package/src/hooks/heartbeat-posttool 2.sh +18 -0
- package/src/hooks/inbox-hook 2.sh +76 -0
- package/src/hooks/post-compact 2.sh +152 -0
- package/src/hooks/pre-compact 2.sh +169 -0
- package/src/hooks/protocol-guardrail 2.sh +10 -0
- package/src/hooks/protocol-pretool-guardrail 2.sh +9 -0
- package/src/hooks/session-stop 2.sh +52 -0
- package/src/kg_populate 2.py +292 -0
- package/src/maintenance 2.py +53 -0
- package/src/memory_backends 2.py +71 -0
- package/src/migrate_embeddings 2.py +124 -0
- package/src/nexo_sdk 2.py +103 -0
- package/src/observability 2.py +199 -0
- package/src/plugin_loader 2.py +217 -0
- package/src/plugins/__init__ 2.py +0 -0
- package/src/plugins/artifact_registry 2.py +450 -0
- package/src/plugins/backup 2.py +127 -0
- package/src/plugins/claims_tools 2.py +119 -0
- package/src/plugins/cognitive_memory 2.py +609 -0
- package/src/plugins/core_rules 2.py +252 -0
- package/src/plugins/cortex 2.py +1155 -0
- package/src/plugins/entities 2.py +67 -0
- package/src/plugins/episodic_memory 2.py +560 -0
- package/src/plugins/evolution 2.py +167 -0
- package/src/plugins/goal_engine 2.py +142 -0
- package/src/plugins/guard 2.py +862 -0
- package/src/plugins/impact 2.py +29 -0
- package/src/plugins/knowledge_graph_tools 2.py +137 -0
- package/src/plugins/media_memory_tools 2.py +98 -0
- package/src/plugins/memory_export 2.py +196 -0
- package/src/plugins/outcomes 2.py +130 -0
- package/src/plugins/personal_scripts 2.py +117 -0
- package/src/plugins/preferences 2.py +47 -0
- package/src/plugins/protocol 2.py +1449 -0
- package/src/plugins/simple_api 2.py +106 -0
- package/src/plugins/skills 2.py +341 -0
- package/src/plugins/state_watchers 2.py +79 -0
- package/src/plugins/update 2.py +986 -0
- package/src/plugins/user_state_tools 2.py +43 -0
- package/src/plugins/workflow 2.py +588 -0
- package/src/protocol_settings 2.py +59 -0
- package/src/public_contribution 2.py +466 -0
- package/src/public_evolution_queue 2.py +241 -0
- package/src/requirements 2.txt +14 -0
- package/src/retroactive_learnings 2.py +373 -0
- package/src/rules/__init__ 2.py +0 -0
- package/src/rules/core-rules 2.json +331 -0
- package/src/rules/migrate 2.py +207 -0
- package/src/runtime_power 2.py +874 -0
- package/src/script_registry 2.py +1559 -0
- package/src/scripts/check-context 2.py +272 -0
- package/src/scripts/deep-sleep/apply_findings 2.py +2327 -0
- package/src/scripts/deep-sleep/collect 2.py +928 -0
- package/src/scripts/deep-sleep/extract 2.py +330 -0
- package/src/scripts/deep-sleep/extract-prompt 2.md +285 -0
- package/src/scripts/deep-sleep/synthesize 2.py +312 -0
- package/src/scripts/deep-sleep/synthesize-prompt 2.md +336 -0
- package/src/scripts/nexo-agent-run 2.py +75 -0
- package/src/scripts/nexo-auto-update 2.py +6 -0
- package/src/scripts/nexo-backup 2.sh +25 -0
- package/src/scripts/nexo-brain-activation 2.sh +140 -0
- package/src/scripts/nexo-catchup 2.py +300 -0
- package/src/scripts/nexo-cognitive-decay 2.py +257 -0
- package/src/scripts/nexo-cortex-cycle 2.py +293 -0
- package/src/scripts/nexo-cron-wrapper 2.sh +53 -0
- package/src/scripts/nexo-daily-self-audit 2.py +2161 -0
- package/src/scripts/nexo-dashboard 2.sh +29 -0
- package/src/scripts/nexo-deep-sleep 2.sh +86 -0
- package/src/scripts/nexo-evolution-run 2.py +1664 -0
- package/src/scripts/nexo-followup-hygiene 2.py +139 -0
- package/src/scripts/nexo-hook-record 2.py +42 -0
- package/src/scripts/nexo-immune 2.py +936 -0
- package/src/scripts/nexo-impact-scorer 2.py +117 -0
- package/src/scripts/nexo-inbox-hook 2.sh +74 -0
- package/src/scripts/nexo-install 2.py +6 -0
- package/src/scripts/nexo-learning-housekeep 2.py +401 -0
- package/src/scripts/nexo-learning-validator 2.py +266 -0
- package/src/scripts/nexo-migrate 2.py +260 -0
- package/src/scripts/nexo-outcome-checker 2.py +127 -0
- package/src/scripts/nexo-postmortem-consolidator 2.py +456 -0
- package/src/scripts/nexo-pre-commit 2.py +120 -0
- package/src/scripts/nexo-prevent-sleep 2.sh +35 -0
- package/src/scripts/nexo-proactive-dashboard 2.py +354 -0
- package/src/scripts/nexo-reflection 2.py +256 -0
- package/src/scripts/nexo-runtime-preflight 2.py +274 -0
- package/src/scripts/nexo-sleep 2.py +631 -0
- package/src/scripts/nexo-snapshot-restore 2.sh +35 -0
- package/src/scripts/nexo-sync-clients 2.py +16 -0
- package/src/scripts/nexo-synthesis 2.py +475 -0
- package/src/scripts/nexo-tcc-approve 2.sh +79 -0
- package/src/scripts/nexo-update 2.sh +306 -0
- package/src/scripts/nexo-watchdog 2.sh +1207 -0
- package/src/scripts/nexo-watchdog-smoke 2.py +119 -0
- package/src/scripts/rehydrate_learnings_from_archive 2.py +245 -0
- package/src/server 2.py +1296 -0
- package/src/skills/run-nexo-audit-phase/guide 2.md +43 -0
- package/src/skills/run-nexo-audit-phase/skill 2.json +59 -0
- package/src/skills/run-nexo-core-fix-cycle/guide 2.md +17 -0
- package/src/skills/run-nexo-core-fix-cycle/script 2.py +276 -0
- package/src/skills/run-nexo-core-fix-cycle/skill 2.json +58 -0
- package/src/skills/run-release-final-audit/guide 2.md +16 -0
- package/src/skills/run-release-final-audit/script 2.py +259 -0
- package/src/skills/run-release-final-audit/skill 2.json +77 -0
- package/src/skills/run-runtime-doctor/guide 2.md +12 -0
- package/src/skills/run-runtime-doctor/script 2.py +21 -0
- package/src/skills/run-runtime-doctor/skill 2.json +25 -0
- package/src/skills_runtime 2.py +932 -0
- package/src/state_watchers_runtime 2.py +475 -0
- package/src/storage_router 2.py +32 -0
- package/src/system_catalog 2.py +786 -0
- package/src/tools_coordination 2.py +103 -0
- package/src/tools_credentials 2.py +68 -0
- package/src/tools_drive 2.py +487 -0
- package/src/tools_hot_context 2.py +163 -0
- package/src/tools_learnings 2.py +612 -0
- package/src/tools_menu 2.py +229 -0
- package/src/tools_reminders 2.py +88 -0
- package/src/tools_reminders_crud 2.py +363 -0
- package/src/tools_sessions 2.py +1054 -0
- package/src/tools_system_catalog 2.py +19 -0
- package/src/tools_task_history 2.py +57 -0
- package/src/tools_transcripts 2.py +98 -0
- package/src/transcript_utils 2.py +412 -0
- package/src/user_context 2.py +46 -0
- package/src/user_data_portability 2.py +328 -0
- package/src/user_state_model 2.py +170 -0
- package/templates/CLAUDE.md 2.template +108 -0
- package/templates/CODEX.AGENTS.md 2.template +66 -0
- package/templates/launchagents/README 2.md +132 -0
- package/templates/launchagents/com.nexo.auto-close-sessions 2.plist +39 -0
- package/templates/launchagents/com.nexo.catchup 2.plist +39 -0
- package/templates/launchagents/com.nexo.cognitive-decay 2.plist +40 -0
- package/templates/launchagents/com.nexo.dashboard 2.plist +43 -0
- package/templates/launchagents/com.nexo.deep-sleep 2.plist +43 -0
- package/templates/launchagents/com.nexo.evolution 2.plist +44 -0
- package/templates/launchagents/com.nexo.followup-hygiene 2.plist +45 -0
- package/templates/launchagents/com.nexo.immune 2.plist +41 -0
- package/templates/launchagents/com.nexo.postmortem 2.plist +45 -0
- package/templates/launchagents/com.nexo.self-audit 2.plist +47 -0
- package/templates/launchagents/com.nexo.synthesis 2.plist +45 -0
- package/templates/launchagents/com.nexo.watchdog 2.plist +37 -0
- package/templates/nexo_helper 2.py +301 -0
- package/templates/openclaw 2.json +13 -0
- package/templates/plugin-template 2.py +40 -0
- package/templates/script-template 2.py +59 -0
- package/templates/script-template 2.sh +13 -0
- package/templates/skill-script-template 2.py +48 -0
- package/templates/skill-template 2.md +33 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
"""
|
|
4
|
+
NEXO Followup Hygiene — Weekly cleanup of followup/reminder statuses.
|
|
5
|
+
|
|
6
|
+
Runs Sundays via LaunchAgent (or manually). Tasks:
|
|
7
|
+
1. Normalize dirty statuses (COMPLETED YYYY-MM-DD -> COMPLETED)
|
|
8
|
+
2. Flag PENDING followups >14 days without updates as STALE
|
|
9
|
+
3. Generate summary of orphaned/forgotten followups for synthesis
|
|
10
|
+
|
|
11
|
+
No CLI needed — this is pure mechanical cleanup.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import sqlite3
|
|
16
|
+
import sys
|
|
17
|
+
from datetime import datetime, date, timedelta
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
NEXO_HOME = Path(os.environ.get("NEXO_HOME", str(Path.home() / ".nexo")))
|
|
21
|
+
_script_dir = Path(__file__).resolve().parent
|
|
22
|
+
_repo_src = _script_dir.parent
|
|
23
|
+
NEXO_CODE = Path(os.environ.get("NEXO_CODE", str(_repo_src) if (_repo_src / "server.py").exists() else str(NEXO_HOME)))
|
|
24
|
+
if str(NEXO_CODE) not in sys.path:
|
|
25
|
+
sys.path.insert(0, str(NEXO_CODE))
|
|
26
|
+
|
|
27
|
+
import db as nexo_db
|
|
28
|
+
|
|
29
|
+
NEXO_DB = NEXO_HOME / "data" / "nexo.db"
|
|
30
|
+
COORD_DIR = NEXO_HOME / "coordination"
|
|
31
|
+
LOG_FILE = NEXO_HOME / "logs" / "followup-hygiene.log"
|
|
32
|
+
|
|
33
|
+
TODAY = date.today().isoformat()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def log(msg):
|
|
37
|
+
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
38
|
+
line = f"[{ts}] {msg}"
|
|
39
|
+
print(line, flush=True)
|
|
40
|
+
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
with open(LOG_FILE, "a") as f:
|
|
42
|
+
f.write(line + "\n")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def main():
|
|
46
|
+
log("=== Followup Hygiene starting ===")
|
|
47
|
+
|
|
48
|
+
if not NEXO_DB.exists():
|
|
49
|
+
log("nexo.db not found")
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
conn = sqlite3.connect(str(NEXO_DB))
|
|
53
|
+
conn.row_factory = sqlite3.Row
|
|
54
|
+
|
|
55
|
+
# 1. Normalize dirty statuses
|
|
56
|
+
dirty_f = conn.execute("SELECT COUNT(*) FROM followups WHERE status LIKE 'COMPLETED %'").fetchone()[0]
|
|
57
|
+
dirty_r = conn.execute("SELECT COUNT(*) FROM reminders WHERE status LIKE 'COMPLETED %'").fetchone()[0]
|
|
58
|
+
|
|
59
|
+
if dirty_f > 0:
|
|
60
|
+
dirty_followups = conn.execute(
|
|
61
|
+
"SELECT id, status FROM followups WHERE status LIKE 'COMPLETED %'"
|
|
62
|
+
).fetchall()
|
|
63
|
+
for row in dirty_followups:
|
|
64
|
+
nexo_db.update_followup(
|
|
65
|
+
str(row["id"]),
|
|
66
|
+
status="COMPLETED",
|
|
67
|
+
history_actor="followup-hygiene",
|
|
68
|
+
history_event="normalized",
|
|
69
|
+
history_note=f"Weekly hygiene normalized dirty status from {row['status']} to COMPLETED.",
|
|
70
|
+
)
|
|
71
|
+
log(f"Normalized {dirty_f} dirty followup statuses")
|
|
72
|
+
|
|
73
|
+
if dirty_r > 0:
|
|
74
|
+
dirty_reminders = conn.execute(
|
|
75
|
+
"SELECT id, status FROM reminders WHERE status LIKE 'COMPLETED %'"
|
|
76
|
+
).fetchall()
|
|
77
|
+
for row in dirty_reminders:
|
|
78
|
+
nexo_db.update_reminder(
|
|
79
|
+
str(row["id"]),
|
|
80
|
+
status="COMPLETED",
|
|
81
|
+
history_actor="followup-hygiene",
|
|
82
|
+
history_event="normalized",
|
|
83
|
+
history_note=f"Weekly hygiene normalized dirty status from {row['status']} to COMPLETED.",
|
|
84
|
+
)
|
|
85
|
+
log(f"Normalized {dirty_r} dirty reminder statuses")
|
|
86
|
+
|
|
87
|
+
# 2. Flag stale followups (PENDING >14 days, no updates)
|
|
88
|
+
cutoff = (date.today() - timedelta(days=14)).isoformat()
|
|
89
|
+
stale = conn.execute(
|
|
90
|
+
"SELECT id, description, date, updated_at FROM followups "
|
|
91
|
+
"WHERE status NOT LIKE 'COMPLETED%' "
|
|
92
|
+
"AND status NOT IN ('DELETED','archived','blocked','waiting') "
|
|
93
|
+
"AND date != '' AND date < ? "
|
|
94
|
+
"ORDER BY date",
|
|
95
|
+
(cutoff,)
|
|
96
|
+
).fetchall()
|
|
97
|
+
|
|
98
|
+
if stale:
|
|
99
|
+
log(f"Found {len(stale)} stale followups (>14 days overdue):")
|
|
100
|
+
for s in stale[:10]:
|
|
101
|
+
log(f" {s['id']}: {s['description'][:60]} (due: {s['date']})")
|
|
102
|
+
|
|
103
|
+
# 3. Orphaned followups (no date, no recent update)
|
|
104
|
+
orphans = conn.execute(
|
|
105
|
+
"SELECT id, description FROM followups "
|
|
106
|
+
"WHERE status NOT LIKE 'COMPLETED%' "
|
|
107
|
+
"AND status NOT IN ('DELETED','archived','blocked','waiting') "
|
|
108
|
+
"AND (date IS NULL OR date = '') "
|
|
109
|
+
"ORDER BY id"
|
|
110
|
+
).fetchall()
|
|
111
|
+
|
|
112
|
+
if orphans:
|
|
113
|
+
log(f"Found {len(orphans)} orphaned followups (no date):")
|
|
114
|
+
for o in orphans[:10]:
|
|
115
|
+
log(f" {o['id']}: {o['description'][:60]}")
|
|
116
|
+
|
|
117
|
+
conn.commit()
|
|
118
|
+
conn.close()
|
|
119
|
+
|
|
120
|
+
# 4. Write summary for synthesis
|
|
121
|
+
summary = {
|
|
122
|
+
"date": TODAY,
|
|
123
|
+
"dirty_normalized": dirty_f + dirty_r,
|
|
124
|
+
"stale_count": len(stale) if stale else 0,
|
|
125
|
+
"orphan_count": len(orphans) if orphans else 0,
|
|
126
|
+
"stale_ids": [s["id"] for s in stale[:20]] if stale else [],
|
|
127
|
+
"orphan_ids": [o["id"] for o in orphans[:20]] if orphans else [],
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
summary_file = COORD_DIR / "followup-hygiene-summary.json"
|
|
131
|
+
summary_file.parent.mkdir(parents=True, exist_ok=True)
|
|
132
|
+
summary_file.write_text(json.dumps(summary, indent=2))
|
|
133
|
+
|
|
134
|
+
log(f"Summary: {dirty_f + dirty_r} normalized, {len(stale) if stale else 0} stale, {len(orphans) if orphans else 0} orphans")
|
|
135
|
+
log("=== Followup Hygiene complete ===")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Tiny CLI to record a hook lifecycle event from a shell hook.
|
|
3
|
+
|
|
4
|
+
Closes Fase 3 item 7 of NEXO-AUDIT-2026-04-11. Bash hooks can call:
|
|
5
|
+
|
|
6
|
+
NEXO_HOME=~/.nexo python3 ~/.nexo/scripts/nexo-hook-record.py \
|
|
7
|
+
--hook session-start --duration-ms 142 --exit $? --session $SID
|
|
8
|
+
|
|
9
|
+
This script is intentionally minimal so it adds <50ms of latency to the
|
|
10
|
+
hook lifecycle. Best-effort: errors are swallowed (the hook itself must
|
|
11
|
+
not fail because observability could not write).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
NEXO_HOME = Path(os.environ.get("NEXO_HOME", str(Path.home() / ".nexo")))
|
|
21
|
+
_script_dir = Path(__file__).resolve().parent
|
|
22
|
+
_repo_src = _script_dir.parent # src/scripts/ -> src/
|
|
23
|
+
NEXO_CODE = Path(
|
|
24
|
+
os.environ.get(
|
|
25
|
+
"NEXO_CODE",
|
|
26
|
+
str(_repo_src) if (_repo_src / "server.py").exists() else str(NEXO_HOME),
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
if str(NEXO_CODE) not in sys.path:
|
|
30
|
+
sys.path.insert(0, str(NEXO_CODE))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> int:
|
|
34
|
+
try:
|
|
35
|
+
from hook_observability import main_cli
|
|
36
|
+
except Exception:
|
|
37
|
+
return 0
|
|
38
|
+
return main_cli(sys.argv[1:])
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
sys.exit(main())
|