nexo-brain 2.3.0 → 2.3.1

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.
Files changed (287) hide show
  1. package/README.md +1 -1
  2. package/package.json +6 -3
  3. package/src/auto_update.py +1 -0
  4. package/src/crons/sync.py +1 -2
  5. package/src/db/_core.py +1 -0
  6. package/src/db/_entities.py +1 -0
  7. package/src/db/_episodic.py +1 -0
  8. package/src/db/_learnings.py +1 -0
  9. package/src/db/_reminders.py +1 -0
  10. package/src/db/_sessions.py +1 -0
  11. package/src/db/_skills.py +1 -0
  12. package/src/plugin_loader.py +1 -0
  13. package/src/plugins/update.py +1 -0
  14. package/src/scripts/deep-sleep/apply_findings.py +1 -0
  15. package/src/scripts/deep-sleep/collect.py +1 -0
  16. package/src/scripts/deep-sleep/extract.py +1 -0
  17. package/src/scripts/deep-sleep/synthesize.py +1 -0
  18. package/src/scripts/nexo-learning-housekeep.py +1 -0
  19. package/src/scripts/nexo-watchdog.sh +19 -11
  20. package/src/server.py +1 -0
  21. package/src/tools_coordination.py +1 -0
  22. package/src/tools_sessions.py +1 -0
  23. package/scripts/migrate-to-unified 2.sh +0 -813
  24. package/scripts/migrate-to-unified.sh +0 -813
  25. package/scripts/migrate-v1.5-to-v1.6 2.py +0 -778
  26. package/scripts/migrate-v1.5-to-v1.6.py +0 -778
  27. package/scripts/migrate-v1.7-to-v1.8 2.py +0 -214
  28. package/scripts/migrate-v1.7-to-v1.8.py +0 -214
  29. package/scripts/nexo-preflight.sh +0 -236
  30. package/scripts/pre-commit-check 2.sh +0 -55
  31. package/scripts/pre-commit-check.sh +0 -55
  32. package/src/__pycache__/auto_close_sessions.cpython-314.pyc +0 -0
  33. package/src/__pycache__/auto_update.cpython-310.pyc +0 -0
  34. package/src/__pycache__/hnsw_index.cpython-310.pyc +0 -0
  35. package/src/__pycache__/hnsw_index.cpython-314.pyc +0 -0
  36. package/src/__pycache__/kg_populate.cpython-310.pyc +0 -0
  37. package/src/__pycache__/knowledge_graph.cpython-310.pyc +0 -0
  38. package/src/__pycache__/plugin_loader.cpython-310.pyc +0 -0
  39. package/src/__pycache__/plugin_loader.cpython-314.pyc +0 -0
  40. package/src/__pycache__/tools_coordination.cpython-310.pyc +0 -0
  41. package/src/__pycache__/tools_credentials.cpython-310.pyc +0 -0
  42. package/src/__pycache__/tools_learnings.cpython-310.pyc +0 -0
  43. package/src/__pycache__/tools_menu.cpython-310.pyc +0 -0
  44. package/src/__pycache__/tools_reminders.cpython-310.pyc +0 -0
  45. package/src/__pycache__/tools_reminders_crud.cpython-310.pyc +0 -0
  46. package/src/__pycache__/tools_sessions.cpython-310.pyc +0 -0
  47. package/src/__pycache__/tools_task_history.cpython-310.pyc +0 -0
  48. package/src/auto_close_sessions 2.py +0 -159
  49. package/src/auto_update 2.py +0 -634
  50. package/src/claim_graph 2.py +0 -323
  51. package/src/cognitive/__init__ 2.py +0 -62
  52. package/src/cognitive/__pycache__/__init__.cpython-310.pyc +0 -0
  53. package/src/cognitive/__pycache__/__init__.cpython-312.pyc +0 -0
  54. package/src/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
  55. package/src/cognitive/__pycache__/_core.cpython-310.pyc +0 -0
  56. package/src/cognitive/__pycache__/_core.cpython-312.pyc +0 -0
  57. package/src/cognitive/__pycache__/_core.cpython-314.pyc +0 -0
  58. package/src/cognitive/__pycache__/_decay.cpython-310.pyc +0 -0
  59. package/src/cognitive/__pycache__/_decay.cpython-312.pyc +0 -0
  60. package/src/cognitive/__pycache__/_decay.cpython-314.pyc +0 -0
  61. package/src/cognitive/__pycache__/_ingest.cpython-310.pyc +0 -0
  62. package/src/cognitive/__pycache__/_ingest.cpython-312.pyc +0 -0
  63. package/src/cognitive/__pycache__/_ingest.cpython-314.pyc +0 -0
  64. package/src/cognitive/__pycache__/_memory.cpython-310.pyc +0 -0
  65. package/src/cognitive/__pycache__/_memory.cpython-312.pyc +0 -0
  66. package/src/cognitive/__pycache__/_memory.cpython-314.pyc +0 -0
  67. package/src/cognitive/__pycache__/_search.cpython-310.pyc +0 -0
  68. package/src/cognitive/__pycache__/_search.cpython-312.pyc +0 -0
  69. package/src/cognitive/__pycache__/_search.cpython-314.pyc +0 -0
  70. package/src/cognitive/__pycache__/_trust.cpython-310.pyc +0 -0
  71. package/src/cognitive/__pycache__/_trust.cpython-312.pyc +0 -0
  72. package/src/cognitive/__pycache__/_trust.cpython-314.pyc +0 -0
  73. package/src/cognitive/_core 2.py +0 -567
  74. package/src/cognitive/_decay 2.py +0 -382
  75. package/src/cognitive/_ingest 2.py +0 -892
  76. package/src/cognitive/_memory 2.py +0 -912
  77. package/src/cognitive/_search 2.py +0 -949
  78. package/src/cognitive/_trust 2.py +0 -464
  79. package/src/crons/__pycache__/sync.cpython-314.pyc +0 -0
  80. package/src/crons/manifest 2.json +0 -106
  81. package/src/crons/sync 2.py +0 -217
  82. package/src/dashboard/__init__ 2.py +0 -0
  83. package/src/dashboard/__pycache__/__init__.cpython-310.pyc +0 -0
  84. package/src/dashboard/__pycache__/app.cpython-310.pyc +0 -0
  85. package/src/dashboard/app 2.py +0 -789
  86. package/src/db/__init__ 2.py +0 -89
  87. package/src/db/__pycache__/__init__.cpython-310.pyc +0 -0
  88. package/src/db/__pycache__/__init__.cpython-312.pyc +0 -0
  89. package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
  90. package/src/db/__pycache__/_core.cpython-310.pyc +0 -0
  91. package/src/db/__pycache__/_core.cpython-312.pyc +0 -0
  92. package/src/db/__pycache__/_core.cpython-314.pyc +0 -0
  93. package/src/db/__pycache__/_credentials.cpython-310.pyc +0 -0
  94. package/src/db/__pycache__/_credentials.cpython-312.pyc +0 -0
  95. package/src/db/__pycache__/_credentials.cpython-314.pyc +0 -0
  96. package/src/db/__pycache__/_cron_runs.cpython-310.pyc +0 -0
  97. package/src/db/__pycache__/_cron_runs.cpython-314.pyc +0 -0
  98. package/src/db/__pycache__/_entities.cpython-310.pyc +0 -0
  99. package/src/db/__pycache__/_entities.cpython-312.pyc +0 -0
  100. package/src/db/__pycache__/_entities.cpython-314.pyc +0 -0
  101. package/src/db/__pycache__/_episodic.cpython-310.pyc +0 -0
  102. package/src/db/__pycache__/_episodic.cpython-312.pyc +0 -0
  103. package/src/db/__pycache__/_episodic.cpython-314.pyc +0 -0
  104. package/src/db/__pycache__/_evolution.cpython-310.pyc +0 -0
  105. package/src/db/__pycache__/_evolution.cpython-312.pyc +0 -0
  106. package/src/db/__pycache__/_evolution.cpython-314.pyc +0 -0
  107. package/src/db/__pycache__/_fts.cpython-310.pyc +0 -0
  108. package/src/db/__pycache__/_fts.cpython-312.pyc +0 -0
  109. package/src/db/__pycache__/_fts.cpython-314.pyc +0 -0
  110. package/src/db/__pycache__/_learnings.cpython-310.pyc +0 -0
  111. package/src/db/__pycache__/_learnings.cpython-312.pyc +0 -0
  112. package/src/db/__pycache__/_learnings.cpython-314.pyc +0 -0
  113. package/src/db/__pycache__/_reminders.cpython-310.pyc +0 -0
  114. package/src/db/__pycache__/_reminders.cpython-312.pyc +0 -0
  115. package/src/db/__pycache__/_reminders.cpython-314.pyc +0 -0
  116. package/src/db/__pycache__/_schema.cpython-310.pyc +0 -0
  117. package/src/db/__pycache__/_schema.cpython-312.pyc +0 -0
  118. package/src/db/__pycache__/_schema.cpython-314.pyc +0 -0
  119. package/src/db/__pycache__/_sessions.cpython-310.pyc +0 -0
  120. package/src/db/__pycache__/_sessions.cpython-312.pyc +0 -0
  121. package/src/db/__pycache__/_sessions.cpython-314.pyc +0 -0
  122. package/src/db/__pycache__/_skills.cpython-310.pyc +0 -0
  123. package/src/db/__pycache__/_skills.cpython-312.pyc +0 -0
  124. package/src/db/__pycache__/_skills.cpython-314.pyc +0 -0
  125. package/src/db/__pycache__/_tasks.cpython-310.pyc +0 -0
  126. package/src/db/__pycache__/_tasks.cpython-312.pyc +0 -0
  127. package/src/db/__pycache__/_tasks.cpython-314.pyc +0 -0
  128. package/src/db/_core 2.py +0 -417
  129. package/src/db/_credentials 2.py +0 -124
  130. package/src/db/_entities 2.py +0 -178
  131. package/src/db/_episodic 2.py +0 -738
  132. package/src/db/_evolution 2.py +0 -54
  133. package/src/db/_fts 2.py +0 -406
  134. package/src/db/_learnings 2.py +0 -168
  135. package/src/db/_reminders 2.py +0 -338
  136. package/src/db/_schema 2.py +0 -364
  137. package/src/db/_sessions 2.py +0 -300
  138. package/src/db/_tasks 2.py +0 -91
  139. package/src/evolution_cycle 2.py +0 -266
  140. package/src/hnsw_index 2.py +0 -254
  141. package/src/hooks/auto_capture 2.py +0 -208
  142. package/src/hooks/caffeinate-guard 2.sh +0 -8
  143. package/src/hooks/capture-session 2.sh +0 -21
  144. package/src/hooks/capture-tool-logs 2.sh +0 -127
  145. package/src/hooks/daily-briefing-check 2.sh +0 -33
  146. package/src/hooks/inbox-hook 2.sh +0 -76
  147. package/src/hooks/post-compact 2.sh +0 -148
  148. package/src/hooks/pre-compact 2.sh +0 -151
  149. package/src/hooks/session-start 2.sh +0 -268
  150. package/src/hooks/session-stop 2.sh +0 -140
  151. package/src/kg_populate 2.py +0 -290
  152. package/src/knowledge_graph 2.py +0 -257
  153. package/src/maintenance 2.py +0 -59
  154. package/src/migrate_embeddings 2.py +0 -122
  155. package/src/plugin_loader 2.py +0 -202
  156. package/src/plugins/__init__ 2.py +0 -0
  157. package/src/plugins/__pycache__/__init__ 2.cpython-310.pyc +0 -0
  158. package/src/plugins/__pycache__/__init__.cpython-310.pyc +0 -0
  159. package/src/plugins/__pycache__/__init__.cpython-314.pyc +0 -0
  160. package/src/plugins/__pycache__/adaptive_mode 2.cpython-310.pyc +0 -0
  161. package/src/plugins/__pycache__/adaptive_mode.cpython-310.pyc +0 -0
  162. package/src/plugins/__pycache__/adaptive_mode.cpython-314.pyc +0 -0
  163. package/src/plugins/__pycache__/agents 2.cpython-310.pyc +0 -0
  164. package/src/plugins/__pycache__/agents.cpython-310.pyc +0 -0
  165. package/src/plugins/__pycache__/artifact_registry 2.cpython-310.pyc +0 -0
  166. package/src/plugins/__pycache__/artifact_registry.cpython-310.pyc +0 -0
  167. package/src/plugins/__pycache__/backup 2.cpython-310.pyc +0 -0
  168. package/src/plugins/__pycache__/backup.cpython-310.pyc +0 -0
  169. package/src/plugins/__pycache__/cognitive_memory 2.cpython-310.pyc +0 -0
  170. package/src/plugins/__pycache__/cognitive_memory.cpython-310.pyc +0 -0
  171. package/src/plugins/__pycache__/core_rules 2.cpython-310.pyc +0 -0
  172. package/src/plugins/__pycache__/core_rules.cpython-310.pyc +0 -0
  173. package/src/plugins/__pycache__/cortex 2.cpython-310.pyc +0 -0
  174. package/src/plugins/__pycache__/cortex.cpython-310.pyc +0 -0
  175. package/src/plugins/__pycache__/entities 2.cpython-310.pyc +0 -0
  176. package/src/plugins/__pycache__/entities.cpython-310.pyc +0 -0
  177. package/src/plugins/__pycache__/episodic_memory 2.cpython-310.pyc +0 -0
  178. package/src/plugins/__pycache__/episodic_memory.cpython-310.pyc +0 -0
  179. package/src/plugins/__pycache__/evolution 2.cpython-310.pyc +0 -0
  180. package/src/plugins/__pycache__/evolution.cpython-310.pyc +0 -0
  181. package/src/plugins/__pycache__/guard 2.cpython-310.pyc +0 -0
  182. package/src/plugins/__pycache__/guard.cpython-310.pyc +0 -0
  183. package/src/plugins/__pycache__/knowledge_graph_tools 2.cpython-310.pyc +0 -0
  184. package/src/plugins/__pycache__/knowledge_graph_tools.cpython-310.pyc +0 -0
  185. package/src/plugins/__pycache__/preferences 2.cpython-310.pyc +0 -0
  186. package/src/plugins/__pycache__/preferences.cpython-310.pyc +0 -0
  187. package/src/plugins/__pycache__/schedule.cpython-310.pyc +0 -0
  188. package/src/plugins/__pycache__/schedule.cpython-314.pyc +0 -0
  189. package/src/plugins/__pycache__/skills.cpython-310.pyc +0 -0
  190. package/src/plugins/__pycache__/skills.cpython-314.pyc +0 -0
  191. package/src/plugins/__pycache__/update 2.cpython-310.pyc +0 -0
  192. package/src/plugins/__pycache__/update.cpython-310.pyc +0 -0
  193. package/src/plugins/adaptive_mode 2.py +0 -805
  194. package/src/plugins/agents 2.py +0 -52
  195. package/src/plugins/artifact_registry 2.py +0 -450
  196. package/src/plugins/backup 2.py +0 -104
  197. package/src/plugins/cognitive_memory 2.py +0 -564
  198. package/src/plugins/core_rules 2.py +0 -252
  199. package/src/plugins/cortex 2.py +0 -299
  200. package/src/plugins/entities 2.py +0 -67
  201. package/src/plugins/episodic_memory 2.py +0 -533
  202. package/src/plugins/evolution 2.py +0 -115
  203. package/src/plugins/guard 2.py +0 -746
  204. package/src/plugins/knowledge_graph_tools 2.py +0 -105
  205. package/src/plugins/preferences 2.py +0 -47
  206. package/src/plugins/update 2.py +0 -256
  207. package/src/requirements 2.txt +0 -12
  208. package/src/rules/__init__ 2.py +0 -0
  209. package/src/rules/core-rules 2.json +0 -331
  210. package/src/rules/migrate 2.py +0 -207
  211. package/src/scripts/__pycache__/nexo-auto-update.cpython-314.pyc +0 -0
  212. package/src/scripts/__pycache__/nexo-catchup.cpython-314.pyc +0 -0
  213. package/src/scripts/__pycache__/nexo-cognitive-decay.cpython-314.pyc +0 -0
  214. package/src/scripts/__pycache__/nexo-daily-self-audit.cpython-314.pyc +0 -0
  215. package/src/scripts/__pycache__/nexo-evolution-run.cpython-314.pyc +0 -0
  216. package/src/scripts/__pycache__/nexo-followup-hygiene.cpython-314.pyc +0 -0
  217. package/src/scripts/__pycache__/nexo-immune.cpython-314.pyc +0 -0
  218. package/src/scripts/__pycache__/nexo-install.cpython-314.pyc +0 -0
  219. package/src/scripts/__pycache__/nexo-learning-housekeep.cpython-314.pyc +0 -0
  220. package/src/scripts/__pycache__/nexo-learning-validator.cpython-314.pyc +0 -0
  221. package/src/scripts/__pycache__/nexo-migrate.cpython-314.pyc +0 -0
  222. package/src/scripts/__pycache__/nexo-postmortem-consolidator.cpython-314.pyc +0 -0
  223. package/src/scripts/__pycache__/nexo-pre-commit.cpython-314.pyc +0 -0
  224. package/src/scripts/__pycache__/nexo-proactive-dashboard.cpython-314.pyc +0 -0
  225. package/src/scripts/__pycache__/nexo-reflection.cpython-314.pyc +0 -0
  226. package/src/scripts/__pycache__/nexo-runtime-preflight.cpython-314.pyc +0 -0
  227. package/src/scripts/__pycache__/nexo-send-email.cpython-314.pyc +0 -0
  228. package/src/scripts/__pycache__/nexo-send-reply.cpython-314.pyc +0 -0
  229. package/src/scripts/__pycache__/nexo-sleep.cpython-314.pyc +0 -0
  230. package/src/scripts/__pycache__/nexo-synthesis.cpython-314.pyc +0 -0
  231. package/src/scripts/__pycache__/nexo-watchdog-smoke.cpython-314.pyc +0 -0
  232. package/src/scripts/check-context 2.py +0 -264
  233. package/src/scripts/nexo-auto-update 2.py +0 -6
  234. package/src/scripts/nexo-backup 2.sh +0 -25
  235. package/src/scripts/nexo-brain-activation 2.sh +0 -140
  236. package/src/scripts/nexo-catchup 2.py +0 -242
  237. package/src/scripts/nexo-cognitive-decay 2.py +0 -182
  238. package/src/scripts/nexo-daily-self-audit 2.py +0 -552
  239. package/src/scripts/nexo-deep-sleep 2.sh +0 -97
  240. package/src/scripts/nexo-evolution-run 2.py +0 -597
  241. package/src/scripts/nexo-followup-hygiene 2.py +0 -112
  242. package/src/scripts/nexo-github-monitor 2.py +0 -256
  243. package/src/scripts/nexo-immune 2.py +0 -927
  244. package/src/scripts/nexo-inbox-hook 2.sh +0 -74
  245. package/src/scripts/nexo-install 2.py +0 -6
  246. package/src/scripts/nexo-learning-housekeep 2.py +0 -245
  247. package/src/scripts/nexo-learning-validator 2.py +0 -207
  248. package/src/scripts/nexo-migrate 2.py +0 -232
  249. package/src/scripts/nexo-postmortem-consolidator 2.py +0 -421
  250. package/src/scripts/nexo-pre-commit 2.py +0 -120
  251. package/src/scripts/nexo-prevent-sleep 2.sh +0 -29
  252. package/src/scripts/nexo-proactive-dashboard 2.py +0 -345
  253. package/src/scripts/nexo-reflection 2.py +0 -253
  254. package/src/scripts/nexo-runtime-preflight 2.py +0 -274
  255. package/src/scripts/nexo-send-email 2.py +0 -25
  256. package/src/scripts/nexo-send-email.py +0 -25
  257. package/src/scripts/nexo-send-reply 2.py +0 -178
  258. package/src/scripts/nexo-send-reply.py +0 -178
  259. package/src/scripts/nexo-sleep 2.py +0 -592
  260. package/src/scripts/nexo-snapshot-restore 2.sh +0 -35
  261. package/src/scripts/nexo-synthesis 2.py +0 -253
  262. package/src/scripts/nexo-tcc-approve 2.sh +0 -79
  263. package/src/scripts/nexo-update 2.sh +0 -161
  264. package/src/scripts/nexo-watchdog 2.sh +0 -878
  265. package/src/scripts/nexo-watchdog-smoke 2.py +0 -119
  266. package/src/server 2.py +0 -733
  267. package/src/storage_router 2.py +0 -32
  268. package/src/tools_coordination 2.py +0 -102
  269. package/src/tools_credentials 2.py +0 -68
  270. package/src/tools_learnings 2.py +0 -220
  271. package/src/tools_menu 2.py +0 -227
  272. package/src/tools_reminders 2.py +0 -86
  273. package/src/tools_reminders_crud 2.py +0 -159
  274. package/src/tools_sessions 2.py +0 -476
  275. package/src/tools_task_history 2.py +0 -57
  276. package/templates/CLAUDE.md 2.template +0 -63
  277. package/templates/openclaw 2.json +0 -13
  278. package/tests/__init__ 2.py +0 -0
  279. package/tests/__init__.py +0 -0
  280. package/tests/conftest 2.py +0 -71
  281. package/tests/conftest.py +0 -71
  282. package/tests/test_cognitive 2.py +0 -205
  283. package/tests/test_cognitive.py +0 -205
  284. package/tests/test_knowledge_graph 2.py +0 -140
  285. package/tests/test_knowledge_graph.py +0 -140
  286. package/tests/test_migrations 2.py +0 -137
  287. package/tests/test_migrations.py +0 -137
@@ -1,214 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- NEXO Migration Script: v1.7.x -> v1.8.0 (Hybrid Architecture)
4
-
5
- Migrates CLAUDE.md to the new hybrid architecture where:
6
- - CLAUDE.md = bootstrap (identity, profile, format, autonomy, project atlas)
7
- - MCP instructions field = tool-coupled behavioral rules
8
- - nexo_context_packet = on-demand area-specific context
9
-
10
- The MCP server now carries all tool-coupled rules in its `instructions` field,
11
- so CLAUDE.md no longer needs to duplicate them. This reduces CLAUDE.md from
12
- ~130 lines to ~50 lines, saving ~3K context tokens per session.
13
-
14
- Safe to run multiple times (idempotent). Creates a backup before modifying.
15
-
16
- Usage:
17
- python3 migrate-v1.7-to-v1.8.py [--dry-run] [--nexo-home /path/to/nexo]
18
- """
19
-
20
- import argparse
21
- import os
22
- import re
23
- import shutil
24
- import sys
25
- from datetime import datetime
26
-
27
-
28
- # Sections that are now in the MCP instructions field and should be REMOVED from CLAUDE.md
29
- MCP_OWNED_SECTIONS = [
30
- "Heartbeat",
31
- "Guard",
32
- "Delegation",
33
- "Reminders & Followups",
34
- "Reminders y Followups",
35
- "Memory",
36
- "Memoria",
37
- "Trust Score",
38
- "Adaptive Mode",
39
- "Dissonance",
40
- "Disonancia",
41
- "Observe the User",
42
- "Observar a Francisco", # legacy personal CLAUDE.md files
43
- "Observar al Usuario",
44
- "Change Log",
45
- "Session Diary",
46
- "Cortex",
47
- "Operational Codex",
48
- ]
49
-
50
- # Sections that STAY in CLAUDE.md (bootstrap layer)
51
- BOOTSTRAP_SECTIONS = [
52
- "Startup",
53
- "User Profile",
54
- "Francisco", # legacy personal CLAUDE.md files
55
- "Formato",
56
- "Format",
57
- "Autonomy",
58
- "Autonomía",
59
- "Project Atlas",
60
- "Atlas de Proyectos",
61
- "Hooks",
62
- "Menu",
63
- "Platforms",
64
- "Plataformas",
65
- "Repo",
66
- ]
67
-
68
-
69
- def find_nexo_home(override=None):
70
- if override:
71
- return override
72
- candidates = [
73
- os.path.expanduser("~/nexo"),
74
- os.path.expanduser("~/.nexo"),
75
- os.path.expanduser("~/claude/nexo-mcp"),
76
- ]
77
- for c in candidates:
78
- if os.path.isdir(c):
79
- return c
80
- return None
81
-
82
-
83
- def find_claude_md():
84
- """Find the CLAUDE.md file that contains NEXO instructions."""
85
- candidates = [
86
- os.path.expanduser("~/.claude/CLAUDE.md"),
87
- os.path.expanduser("~/CLAUDE.md"),
88
- ]
89
- for c in candidates:
90
- if os.path.isfile(c):
91
- return c
92
- return None
93
-
94
-
95
- def parse_sections(content):
96
- """Parse markdown into sections by ## headers."""
97
- sections = []
98
- current_header = None
99
- current_lines = []
100
-
101
- for line in content.split("\n"):
102
- if line.startswith("## "):
103
- if current_header is not None:
104
- sections.append((current_header, "\n".join(current_lines)))
105
- current_header = line[3:].strip()
106
- current_lines = [line]
107
- else:
108
- current_lines.append(line)
109
-
110
- if current_header is not None:
111
- sections.append((current_header, "\n".join(current_lines)))
112
- elif current_lines:
113
- sections.append(("_preamble", "\n".join(current_lines)))
114
-
115
- return sections
116
-
117
-
118
- def is_mcp_owned(header):
119
- """Check if a section header matches an MCP-owned section."""
120
- header_lower = header.lower()
121
- for section in MCP_OWNED_SECTIONS:
122
- if section.lower() in header_lower:
123
- return True
124
- return False
125
-
126
-
127
- def migrate_claude_md(path, dry_run=False):
128
- """Slim down CLAUDE.md by removing MCP-owned sections."""
129
- with open(path, "r") as f:
130
- content = f.read()
131
-
132
- original_lines = len(content.strip().split("\n"))
133
- sections = parse_sections(content)
134
-
135
- # Separate preamble, bootstrap, and MCP-owned sections
136
- preamble = ""
137
- kept = []
138
- removed = []
139
-
140
- for header, body in sections:
141
- if header == "_preamble":
142
- preamble = body
143
- elif is_mcp_owned(header):
144
- removed.append(header)
145
- else:
146
- kept.append((header, body))
147
-
148
- if not removed:
149
- print(" CLAUDE.md already migrated (no MCP-owned sections found).")
150
- return False
151
-
152
- # Add hybrid architecture note to preamble
153
- if "MCP instructions" not in preamble and "instructions" not in preamble:
154
- preamble = preamble.rstrip() + (
155
- "\nTool-coupled behavioral rules (heartbeat, guard, trust, memory, diary) "
156
- "now live in the MCP server instructions field and are injected automatically.\n"
157
- )
158
-
159
- # Reconstruct
160
- new_content = preamble + "\n"
161
- for header, body in kept:
162
- new_content += "\n" + body + "\n"
163
-
164
- new_lines = len(new_content.strip().split("\n"))
165
-
166
- print(f" Sections removed (now in MCP): {', '.join(removed)}")
167
- print(f" Lines: {original_lines} → {new_lines} (saved {original_lines - new_lines})")
168
-
169
- if dry_run:
170
- print(" [DRY RUN] No changes written.")
171
- return True
172
-
173
- # Backup
174
- backup = path + f".backup-{datetime.now().strftime(\"%Y%m%d-%H%M%S\")}"
175
- shutil.copy2(path, backup)
176
- print(f" Backup: {backup}")
177
-
178
- with open(path, "w") as f:
179
- f.write(new_content)
180
- print(" CLAUDE.md updated.")
181
- return True
182
-
183
-
184
- def main():
185
- parser = argparse.ArgumentParser(description="Migrate NEXO to v1.8 hybrid architecture")
186
- parser.add_argument("--dry-run", action="store_true", help="Show what would change without modifying files")
187
- parser.add_argument("--nexo-home", help="Override NEXO home directory")
188
- args = parser.parse_args()
189
-
190
- print("NEXO v1.7 → v1.8 Migration (Hybrid Architecture)")
191
- print("=" * 50)
192
- print()
193
-
194
- # Step 1: Find and migrate CLAUDE.md
195
- claude_md = find_claude_md()
196
- if claude_md:
197
- print(f"Found CLAUDE.md: {claude_md}")
198
- migrate_claude_md(claude_md, dry_run=args.dry_run)
199
- else:
200
- print("No CLAUDE.md found (skipping).")
201
-
202
- print()
203
- print("Migration complete.")
204
- print()
205
- print("What changed:")
206
- print(" - CLAUDE.md now contains only bootstrap (identity, format, autonomy)")
207
- print(" - Tool-coupled rules are in the MCP server instructions field")
208
- print(" - Context-specific rules load on-demand via nexo_context_packet")
209
- print()
210
- print("The MCP server must be restarted for instructions to take effect.")
211
-
212
-
213
- if __name__ == "__main__":
214
- main()
@@ -1,214 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- NEXO Migration Script: v1.7.x -> v1.8.0 (Hybrid Architecture)
4
-
5
- Migrates CLAUDE.md to the new hybrid architecture where:
6
- - CLAUDE.md = bootstrap (identity, profile, format, autonomy, project atlas)
7
- - MCP instructions field = tool-coupled behavioral rules
8
- - nexo_context_packet = on-demand area-specific context
9
-
10
- The MCP server now carries all tool-coupled rules in its `instructions` field,
11
- so CLAUDE.md no longer needs to duplicate them. This reduces CLAUDE.md from
12
- ~130 lines to ~50 lines, saving ~3K context tokens per session.
13
-
14
- Safe to run multiple times (idempotent). Creates a backup before modifying.
15
-
16
- Usage:
17
- python3 migrate-v1.7-to-v1.8.py [--dry-run] [--nexo-home /path/to/nexo]
18
- """
19
-
20
- import argparse
21
- import os
22
- import re
23
- import shutil
24
- import sys
25
- from datetime import datetime
26
-
27
-
28
- # Sections that are now in the MCP instructions field and should be REMOVED from CLAUDE.md
29
- MCP_OWNED_SECTIONS = [
30
- "Heartbeat",
31
- "Guard",
32
- "Delegation",
33
- "Reminders & Followups",
34
- "Reminders y Followups",
35
- "Memory",
36
- "Memoria",
37
- "Trust Score",
38
- "Adaptive Mode",
39
- "Dissonance",
40
- "Disonancia",
41
- "Observe the User",
42
- "Observar a {{user}}", # legacy personal CLAUDE.md files
43
- "Observar al Usuario",
44
- "Change Log",
45
- "Session Diary",
46
- "Cortex",
47
- "Operational Codex",
48
- ]
49
-
50
- # Sections that STAY in CLAUDE.md (bootstrap layer)
51
- BOOTSTRAP_SECTIONS = [
52
- "Startup",
53
- "User Profile",
54
- "{{user_name}}", # legacy personal CLAUDE.md files
55
- "Formato",
56
- "Format",
57
- "Autonomy",
58
- "Autonomía",
59
- "Project Atlas",
60
- "Atlas de Proyectos",
61
- "Hooks",
62
- "Menu",
63
- "Platforms",
64
- "Plataformas",
65
- "Repo",
66
- ]
67
-
68
-
69
- def find_nexo_home(override=None):
70
- if override:
71
- return override
72
- candidates = [
73
- os.path.expanduser("~/nexo"),
74
- os.path.expanduser("~/.nexo"),
75
- os.path.expanduser("~/claude/nexo-mcp"),
76
- ]
77
- for c in candidates:
78
- if os.path.isdir(c):
79
- return c
80
- return None
81
-
82
-
83
- def find_claude_md():
84
- """Find the CLAUDE.md file that contains NEXO instructions."""
85
- candidates = [
86
- os.path.expanduser("~/.claude/CLAUDE.md"),
87
- os.path.expanduser("~/CLAUDE.md"),
88
- ]
89
- for c in candidates:
90
- if os.path.isfile(c):
91
- return c
92
- return None
93
-
94
-
95
- def parse_sections(content):
96
- """Parse markdown into sections by ## headers."""
97
- sections = []
98
- current_header = None
99
- current_lines = []
100
-
101
- for line in content.split("\n"):
102
- if line.startswith("## "):
103
- if current_header is not None:
104
- sections.append((current_header, "\n".join(current_lines)))
105
- current_header = line[3:].strip()
106
- current_lines = [line]
107
- else:
108
- current_lines.append(line)
109
-
110
- if current_header is not None:
111
- sections.append((current_header, "\n".join(current_lines)))
112
- elif current_lines:
113
- sections.append(("_preamble", "\n".join(current_lines)))
114
-
115
- return sections
116
-
117
-
118
- def is_mcp_owned(header):
119
- """Check if a section header matches an MCP-owned section."""
120
- header_lower = header.lower()
121
- for section in MCP_OWNED_SECTIONS:
122
- if section.lower() in header_lower:
123
- return True
124
- return False
125
-
126
-
127
- def migrate_claude_md(path, dry_run=False):
128
- """Slim down CLAUDE.md by removing MCP-owned sections."""
129
- with open(path, "r") as f:
130
- content = f.read()
131
-
132
- original_lines = len(content.strip().split("\n"))
133
- sections = parse_sections(content)
134
-
135
- # Separate preamble, bootstrap, and MCP-owned sections
136
- preamble = ""
137
- kept = []
138
- removed = []
139
-
140
- for header, body in sections:
141
- if header == "_preamble":
142
- preamble = body
143
- elif is_mcp_owned(header):
144
- removed.append(header)
145
- else:
146
- kept.append((header, body))
147
-
148
- if not removed:
149
- print(" CLAUDE.md already migrated (no MCP-owned sections found).")
150
- return False
151
-
152
- # Add hybrid architecture note to preamble
153
- if "MCP instructions" not in preamble and "instructions" not in preamble:
154
- preamble = preamble.rstrip() + (
155
- "\nTool-coupled behavioral rules (heartbeat, guard, trust, memory, diary) "
156
- "now live in the MCP server instructions field and are injected automatically.\n"
157
- )
158
-
159
- # Reconstruct
160
- new_content = preamble + "\n"
161
- for header, body in kept:
162
- new_content += "\n" + body + "\n"
163
-
164
- new_lines = len(new_content.strip().split("\n"))
165
-
166
- print(f" Sections removed (now in MCP): {', '.join(removed)}")
167
- print(f" Lines: {original_lines} → {new_lines} (saved {original_lines - new_lines})")
168
-
169
- if dry_run:
170
- print(" [DRY RUN] No changes written.")
171
- return True
172
-
173
- # Backup
174
- backup = path + f".backup-{datetime.now().strftime(\"%Y%m%d-%H%M%S\")}"
175
- shutil.copy2(path, backup)
176
- print(f" Backup: {backup}")
177
-
178
- with open(path, "w") as f:
179
- f.write(new_content)
180
- print(" CLAUDE.md updated.")
181
- return True
182
-
183
-
184
- def main():
185
- parser = argparse.ArgumentParser(description="Migrate NEXO to v1.8 hybrid architecture")
186
- parser.add_argument("--dry-run", action="store_true", help="Show what would change without modifying files")
187
- parser.add_argument("--nexo-home", help="Override NEXO home directory")
188
- args = parser.parse_args()
189
-
190
- print("NEXO v1.7 → v1.8 Migration (Hybrid Architecture)")
191
- print("=" * 50)
192
- print()
193
-
194
- # Step 1: Find and migrate CLAUDE.md
195
- claude_md = find_claude_md()
196
- if claude_md:
197
- print(f"Found CLAUDE.md: {claude_md}")
198
- migrate_claude_md(claude_md, dry_run=args.dry_run)
199
- else:
200
- print("No CLAUDE.md found (skipping).")
201
-
202
- print()
203
- print("Migration complete.")
204
- print()
205
- print("What changed:")
206
- print(" - CLAUDE.md now contains only bootstrap (identity, format, autonomy)")
207
- print(" - Tool-coupled rules are in the MCP server instructions field")
208
- print(" - Context-specific rules load on-demand via nexo_context_packet")
209
- print()
210
- print("The MCP server must be restarted for instructions to take effect.")
211
-
212
-
213
- if __name__ == "__main__":
214
- main()
@@ -1,236 +0,0 @@
1
- #!/bin/bash
2
- # ============================================================================
3
- # NEXO Preflight — CI / manual verification script
4
- # Checks: Python syntax, shell syntax, manifest<->file consistency,
5
- # manifest<->watchdog consistency
6
- # Exit code: 0 if all PASS, 1 if any FAIL
7
- # Usage: bash scripts/nexo-preflight.sh
8
- # ============================================================================
9
- set -uo pipefail
10
-
11
- REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12
- SRC="$REPO_ROOT/src"
13
- MANIFEST="$SRC/crons/manifest.json"
14
- WATCHDOG="$SRC/scripts/nexo-watchdog.sh"
15
-
16
- PASS=0
17
- FAIL=0
18
- WARN=0
19
-
20
- pass() { echo " PASS $1"; ((PASS++)); }
21
- fail() { echo " FAIL $1"; ((FAIL++)); }
22
- warn() { echo " WARN $1"; ((WARN++)); }
23
-
24
- echo "============================================================"
25
- echo "NEXO Preflight — $(date '+%Y-%m-%d %H:%M:%S')"
26
- echo "============================================================"
27
-
28
- # ── 1. py_compile for all Python scripts in src/scripts/ ──────────────────
29
- echo ""
30
- # Non-core scripts to exclude from compilation checks
31
- NON_CORE="check-context.py"
32
-
33
- echo "--- Check 1: Python syntax (src/scripts/*.py) ---"
34
- for pyfile in "$SRC"/scripts/*.py; do
35
- # Skip " 2" duplicate files (backup copies)
36
- [[ "$pyfile" == *" 2"* ]] && continue
37
- [ -f "$pyfile" ] || continue
38
- name=$(basename "$pyfile")
39
- # Skip non-core scripts
40
- for skip in $NON_CORE; do
41
- [[ "$name" == "$skip" ]] && continue 2
42
- done
43
- if python3 -m py_compile "$pyfile" 2>/dev/null; then
44
- pass "$name"
45
- else
46
- fail "$name — py_compile error"
47
- fi
48
- done
49
-
50
- # ── 2. py_compile for auto_close_sessions.py ──────────────────────────────
51
- echo ""
52
- echo "--- Check 2: Python syntax (auto_close_sessions.py) ---"
53
- ACS="$SRC/auto_close_sessions.py"
54
- if [ -f "$ACS" ]; then
55
- if python3 -m py_compile "$ACS" 2>/dev/null; then
56
- pass "auto_close_sessions.py"
57
- else
58
- fail "auto_close_sessions.py — py_compile error"
59
- fi
60
- else
61
- fail "auto_close_sessions.py — file not found"
62
- fi
63
-
64
- # ── 3. bash -n for all shell scripts in src/scripts/ ─────────────────────
65
- echo ""
66
- echo "--- Check 3: Shell syntax (src/scripts/*.sh) ---"
67
- for shfile in "$SRC"/scripts/*.sh; do
68
- # Skip " 2" duplicate files (backup copies)
69
- [[ "$shfile" == *" 2"* ]] && continue
70
- [ -f "$shfile" ] || continue
71
- name=$(basename "$shfile")
72
- if bash -n "$shfile" 2>/dev/null; then
73
- pass "$name"
74
- else
75
- fail "$name — bash -n syntax error"
76
- fi
77
- done
78
-
79
- # ── 4. Manifest<->file consistency ────────────────────────────────────────
80
- echo ""
81
- echo "--- Check 4: Manifest crons have existing script files ---"
82
- if [ ! -f "$MANIFEST" ]; then
83
- fail "manifest.json not found at $MANIFEST"
84
- else
85
- # Extract script paths from manifest crons
86
- cron_scripts=$(python3 -c "
87
- import json, sys
88
- try:
89
- m = json.load(open('$MANIFEST'))
90
- for c in m.get('crons', []):
91
- print(c.get('id', '?') + '|' + c.get('script', ''))
92
- except Exception as e:
93
- print(f'ERROR|{e}', file=sys.stderr)
94
- sys.exit(1)
95
- " 2>/dev/null)
96
-
97
- if [ $? -ne 0 ]; then
98
- fail "manifest.json — cannot parse JSON"
99
- else
100
- while IFS='|' read -r cron_id script_path; do
101
- [ -z "$script_path" ] && continue
102
- full_path="$SRC/$script_path"
103
- if [ -f "$full_path" ]; then
104
- pass "cron '$cron_id' -> $script_path exists"
105
- else
106
- fail "cron '$cron_id' -> $script_path NOT FOUND"
107
- fi
108
- done <<< "$cron_scripts"
109
- fi
110
- fi
111
-
112
- # ── 5. Manifest<->watchdog MONITORS consistency ──────────────────────────
113
- echo ""
114
- echo "--- Check 5: Manifest crons present in watchdog MONITORS ---"
115
- if [ ! -f "$WATCHDOG" ]; then
116
- fail "nexo-watchdog.sh not found at $WATCHDOG"
117
- else
118
- # The watchdog dynamically builds MONITORS from manifest.json via
119
- # _build_monitors_from_manifest(). Verify that function exists and
120
- # references the manifest, plus check that any hardcoded PERSONAL_MONITORS
121
- # use valid com.nexo.* plist IDs.
122
-
123
- if grep -q "_build_monitors_from_manifest" "$WATCHDOG"; then
124
- pass "watchdog dynamically loads MONITORS from manifest.json"
125
- else
126
- fail "watchdog does NOT reference _build_monitors_from_manifest"
127
- fi
128
-
129
- if grep -q 'MANIFEST_FILE' "$WATCHDOG"; then
130
- pass "watchdog references MANIFEST_FILE"
131
- else
132
- fail "watchdog does NOT reference MANIFEST_FILE for dynamic loading"
133
- fi
134
-
135
- # Check that any hardcoded personal monitors have valid format
136
- personal_count=$(grep -c '|com\.nexo\.' "$WATCHDOG" 2>/dev/null || echo 0)
137
- if [ "$personal_count" -gt 0 ]; then
138
- pass "watchdog has $personal_count personal monitor entries"
139
- else
140
- pass "watchdog has no hardcoded personal monitors (all from manifest)"
141
- fi
142
- fi
143
-
144
- # ── 6. Manifest<->README consistency ─────────────────────────────────────
145
- echo ""
146
- echo "--- Check 6: Manifest crons mentioned in README ---"
147
- README="$REPO_ROOT/README.md"
148
- if [ -f "$README" ] && [ -f "$MANIFEST" ]; then
149
- manifest_ids=$(python3 -c "
150
- import json
151
- m = json.load(open('$MANIFEST'))
152
- for c in m.get('crons', []):
153
- print(c['id'])
154
- " 2>/dev/null)
155
-
156
- for cid in $manifest_ids; do
157
- if grep -qE "\*\*${cid}\*\*|${cid}" "$README" 2>/dev/null; then
158
- pass "cron '$cid' documented in README"
159
- else
160
- fail "cron '$cid' NOT in README"
161
- fi
162
- done
163
- else
164
- warn "README.md or manifest.json not found, skipping"
165
- fi
166
-
167
- # ── 7. Smoke tests ──────────────────────────────────────────────────────
168
- echo ""
169
- echo "--- Check 7: Smoke tests ---"
170
-
171
- # 7a: catchup weekday conversion (manifest 0=Sunday -> python 6)
172
- WEEKDAY_TEST=$(python3 -c "
173
- # Simulate the conversion from catchup.py
174
- manifest_weekday = 0 # Sunday in cron/launchd
175
- py_weekday = (manifest_weekday - 1) % 7 # Should be 6 (Sunday in Python)
176
- assert py_weekday == 6, f'Expected 6 (Sunday), got {py_weekday}'
177
- # Also test Monday
178
- assert (1 - 1) % 7 == 0, 'Monday should be 0'
179
- # Saturday
180
- assert (6 - 1) % 7 == 5, 'Saturday should be 5'
181
- print('OK')
182
- " 2>&1)
183
- if [ "$WEEKDAY_TEST" = "OK" ]; then
184
- pass "catchup weekday conversion (manifest 0=Sun -> python 6)"
185
- else
186
- fail "catchup weekday conversion: $WEEKDAY_TEST"
187
- fi
188
-
189
- # 7b: change_log schema uses what_changed (not description)
190
- SCHEMA_TEST=$(python3 -c "
191
- import sys
192
- sys.path.insert(0, '$SRC')
193
- # Verify change_log columns match what learning-housekeep uses
194
- with open('$SRC/db/_core.py') as f:
195
- core = f.read()
196
- if 'what_changed' in core:
197
- print('OK')
198
- else:
199
- print('FAIL: what_changed not found in _core.py')
200
- " 2>&1)
201
- if [ "$SCHEMA_TEST" = "OK" ]; then
202
- pass "change_log schema uses what_changed (matches reconciler)"
203
- else
204
- fail "change_log schema: $SCHEMA_TEST"
205
- fi
206
-
207
- # 7c: reconciler queries use correct columns for change_log
208
- RECONCILER_TEST=$(python3 -c "
209
- with open('$SRC/scripts/nexo-learning-housekeep.py') as f:
210
- code = f.read()
211
- # Find the change_log section of _reconcile_decision_outcome
212
- cl_section = code[code.index('# Check change_log'):code.index('return None', code.index('# Check change_log'))]
213
- if 'what_changed LIKE' in cl_section:
214
- print('OK')
215
- else:
216
- print('FAIL: change_log section does not use what_changed')
217
- " 2>&1)
218
- if [ "$RECONCILER_TEST" = "OK" ]; then
219
- pass "reconciler uses correct change_log columns"
220
- else
221
- fail "reconciler columns: $RECONCILER_TEST"
222
- fi
223
-
224
- # ── Summary ───────────────────────────────────────────────────────────────
225
- echo ""
226
- echo "============================================================"
227
- echo "Results: $PASS PASS, $FAIL FAIL, $WARN WARN"
228
- echo "============================================================"
229
-
230
- if [ "$FAIL" -gt 0 ]; then
231
- echo "PREFLIGHT FAILED"
232
- exit 1
233
- else
234
- echo "PREFLIGHT OK"
235
- exit 0
236
- fi