nexo-brain 2.3.0 → 2.3.2
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 +1 -1
- package/bin/nexo-brain.js +92 -9
- package/bin/postinstall.js +22 -15
- package/package.json +7 -4
- package/src/auto_update.py +194 -5
- package/src/crons/sync.py +6 -2
- package/src/db/_core.py +1 -0
- package/src/db/_entities.py +1 -0
- package/src/db/_episodic.py +1 -0
- package/src/db/_learnings.py +1 -0
- package/src/db/_reminders.py +1 -0
- package/src/db/_schema.py +11 -1
- package/src/db/_sessions.py +1 -0
- package/src/db/_skills.py +1 -0
- package/src/hooks/capture-tool-logs.sh +23 -6
- package/src/hooks/session-start.sh +4 -3
- package/src/plugin_loader.py +1 -0
- package/src/plugins/update.py +377 -26
- package/src/scripts/deep-sleep/apply_findings.py +1 -0
- package/src/scripts/deep-sleep/collect.py +1 -0
- package/src/scripts/deep-sleep/extract.py +1 -0
- package/src/scripts/deep-sleep/synthesize.py +1 -0
- package/src/scripts/nexo-catchup.py +29 -4
- package/src/scripts/nexo-daily-self-audit.py +21 -1
- package/src/scripts/nexo-evolution-run.py +21 -1
- package/src/scripts/nexo-learning-housekeep.py +1 -0
- package/src/scripts/nexo-postmortem-consolidator.py +34 -9
- package/src/scripts/nexo-sleep.py +32 -10
- package/src/scripts/nexo-synthesis.py +29 -9
- package/src/scripts/nexo-update.sh +109 -7
- package/src/scripts/nexo-watchdog.sh +122 -58
- package/src/server.py +66 -1
- package/src/tools_coordination.py +1 -0
- package/src/tools_sessions.py +1 -0
- package/scripts/migrate-to-unified 2.sh +0 -813
- package/scripts/migrate-to-unified.sh +0 -813
- package/scripts/migrate-v1.5-to-v1.6 2.py +0 -778
- package/scripts/migrate-v1.5-to-v1.6.py +0 -778
- package/scripts/migrate-v1.7-to-v1.8 2.py +0 -214
- package/scripts/migrate-v1.7-to-v1.8.py +0 -214
- package/scripts/nexo-preflight.sh +0 -236
- package/scripts/pre-commit-check 2.sh +0 -55
- package/scripts/pre-commit-check.sh +0 -55
- package/src/__pycache__/auto_close_sessions.cpython-314.pyc +0 -0
- package/src/__pycache__/auto_update.cpython-310.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-310.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-314.pyc +0 -0
- package/src/__pycache__/kg_populate.cpython-310.pyc +0 -0
- package/src/__pycache__/knowledge_graph.cpython-310.pyc +0 -0
- package/src/__pycache__/plugin_loader.cpython-310.pyc +0 -0
- package/src/__pycache__/plugin_loader.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_coordination.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_credentials.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_learnings.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_menu.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_reminders.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_reminders_crud.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_sessions.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_task_history.cpython-310.pyc +0 -0
- package/src/auto_close_sessions 2.py +0 -159
- package/src/auto_update 2.py +0 -634
- package/src/claim_graph 2.py +0 -323
- package/src/cognitive/__init__ 2.py +0 -62
- package/src/cognitive/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-314.pyc +0 -0
- package/src/cognitive/_core 2.py +0 -567
- package/src/cognitive/_decay 2.py +0 -382
- package/src/cognitive/_ingest 2.py +0 -892
- package/src/cognitive/_memory 2.py +0 -912
- package/src/cognitive/_search 2.py +0 -949
- package/src/cognitive/_trust 2.py +0 -464
- package/src/crons/__pycache__/sync.cpython-314.pyc +0 -0
- package/src/crons/manifest 2.json +0 -106
- package/src/crons/sync 2.py +0 -217
- package/src/dashboard/__init__ 2.py +0 -0
- package/src/dashboard/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/dashboard/__pycache__/app.cpython-310.pyc +0 -0
- package/src/dashboard/app 2.py +0 -789
- package/src/db/__init__ 2.py +0 -89
- package/src/db/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/db/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_cron_runs.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_cron_runs.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_skills.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_skills.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_skills.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-314.pyc +0 -0
- package/src/db/_core 2.py +0 -417
- package/src/db/_credentials 2.py +0 -124
- package/src/db/_entities 2.py +0 -178
- package/src/db/_episodic 2.py +0 -738
- package/src/db/_evolution 2.py +0 -54
- package/src/db/_fts 2.py +0 -406
- package/src/db/_learnings 2.py +0 -168
- package/src/db/_reminders 2.py +0 -338
- package/src/db/_schema 2.py +0 -364
- package/src/db/_sessions 2.py +0 -300
- package/src/db/_tasks 2.py +0 -91
- package/src/evolution_cycle 2.py +0 -266
- package/src/hnsw_index 2.py +0 -254
- package/src/hooks/auto_capture 2.py +0 -208
- package/src/hooks/caffeinate-guard 2.sh +0 -8
- package/src/hooks/capture-session 2.sh +0 -21
- package/src/hooks/capture-tool-logs 2.sh +0 -127
- package/src/hooks/daily-briefing-check 2.sh +0 -33
- package/src/hooks/inbox-hook 2.sh +0 -76
- package/src/hooks/post-compact 2.sh +0 -148
- package/src/hooks/pre-compact 2.sh +0 -151
- package/src/hooks/session-start 2.sh +0 -268
- package/src/hooks/session-stop 2.sh +0 -140
- package/src/kg_populate 2.py +0 -290
- package/src/knowledge_graph 2.py +0 -257
- package/src/maintenance 2.py +0 -59
- package/src/migrate_embeddings 2.py +0 -122
- package/src/plugin_loader 2.py +0 -202
- package/src/plugins/__init__ 2.py +0 -0
- package/src/plugins/__pycache__/__init__ 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/agents 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/agents.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/backup 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/backup.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/core_rules 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/core_rules.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cortex 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cortex.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/entities 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/entities.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/evolution 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/evolution.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/guard 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/guard.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/preferences 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/preferences.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/schedule.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/schedule.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/skills.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/skills.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/update 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/update.cpython-310.pyc +0 -0
- package/src/plugins/adaptive_mode 2.py +0 -805
- package/src/plugins/agents 2.py +0 -52
- package/src/plugins/artifact_registry 2.py +0 -450
- package/src/plugins/backup 2.py +0 -104
- package/src/plugins/cognitive_memory 2.py +0 -564
- package/src/plugins/core_rules 2.py +0 -252
- package/src/plugins/cortex 2.py +0 -299
- package/src/plugins/entities 2.py +0 -67
- package/src/plugins/episodic_memory 2.py +0 -533
- package/src/plugins/evolution 2.py +0 -115
- package/src/plugins/guard 2.py +0 -746
- package/src/plugins/knowledge_graph_tools 2.py +0 -105
- package/src/plugins/preferences 2.py +0 -47
- package/src/plugins/update 2.py +0 -256
- package/src/requirements 2.txt +0 -12
- package/src/rules/__init__ 2.py +0 -0
- package/src/rules/core-rules 2.json +0 -331
- package/src/rules/migrate 2.py +0 -207
- package/src/scripts/__pycache__/nexo-auto-update.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-catchup.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-cognitive-decay.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-daily-self-audit.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-evolution-run.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-followup-hygiene.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-immune.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-install.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-learning-housekeep.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-learning-validator.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-migrate.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-postmortem-consolidator.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-pre-commit.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-proactive-dashboard.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-reflection.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-runtime-preflight.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-send-email.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-send-reply.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-sleep.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-synthesis.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-watchdog-smoke.cpython-314.pyc +0 -0
- package/src/scripts/check-context 2.py +0 -264
- package/src/scripts/nexo-auto-update 2.py +0 -6
- package/src/scripts/nexo-backup 2.sh +0 -25
- package/src/scripts/nexo-brain-activation 2.sh +0 -140
- package/src/scripts/nexo-catchup 2.py +0 -242
- package/src/scripts/nexo-cognitive-decay 2.py +0 -182
- package/src/scripts/nexo-daily-self-audit 2.py +0 -552
- package/src/scripts/nexo-deep-sleep 2.sh +0 -97
- package/src/scripts/nexo-evolution-run 2.py +0 -597
- package/src/scripts/nexo-followup-hygiene 2.py +0 -112
- package/src/scripts/nexo-github-monitor 2.py +0 -256
- package/src/scripts/nexo-immune 2.py +0 -927
- package/src/scripts/nexo-inbox-hook 2.sh +0 -74
- package/src/scripts/nexo-install 2.py +0 -6
- package/src/scripts/nexo-learning-housekeep 2.py +0 -245
- package/src/scripts/nexo-learning-validator 2.py +0 -207
- package/src/scripts/nexo-migrate 2.py +0 -232
- package/src/scripts/nexo-postmortem-consolidator 2.py +0 -421
- package/src/scripts/nexo-pre-commit 2.py +0 -120
- package/src/scripts/nexo-prevent-sleep 2.sh +0 -29
- package/src/scripts/nexo-proactive-dashboard 2.py +0 -345
- package/src/scripts/nexo-reflection 2.py +0 -253
- package/src/scripts/nexo-runtime-preflight 2.py +0 -274
- package/src/scripts/nexo-send-email 2.py +0 -25
- package/src/scripts/nexo-send-email.py +0 -25
- package/src/scripts/nexo-send-reply 2.py +0 -178
- package/src/scripts/nexo-send-reply.py +0 -178
- package/src/scripts/nexo-sleep 2.py +0 -592
- package/src/scripts/nexo-snapshot-restore 2.sh +0 -35
- package/src/scripts/nexo-synthesis 2.py +0 -253
- package/src/scripts/nexo-tcc-approve 2.sh +0 -79
- package/src/scripts/nexo-update 2.sh +0 -161
- package/src/scripts/nexo-watchdog 2.sh +0 -878
- package/src/scripts/nexo-watchdog-smoke 2.py +0 -119
- package/src/server 2.py +0 -733
- package/src/storage_router 2.py +0 -32
- package/src/tools_coordination 2.py +0 -102
- package/src/tools_credentials 2.py +0 -68
- package/src/tools_learnings 2.py +0 -220
- package/src/tools_menu 2.py +0 -227
- package/src/tools_reminders 2.py +0 -86
- package/src/tools_reminders_crud 2.py +0 -159
- package/src/tools_sessions 2.py +0 -476
- package/src/tools_task_history 2.py +0 -57
- package/templates/CLAUDE.md 2.template +0 -63
- package/templates/openclaw 2.json +0 -13
- package/tests/__init__ 2.py +0 -0
- package/tests/__init__.py +0 -0
- package/tests/conftest 2.py +0 -71
- package/tests/conftest.py +0 -71
- package/tests/test_cognitive 2.py +0 -205
- package/tests/test_cognitive.py +0 -205
- package/tests/test_knowledge_graph 2.py +0 -140
- package/tests/test_knowledge_graph.py +0 -140
- package/tests/test_migrations 2.py +0 -137
- package/tests/test_migrations.py +0 -137
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
"""NEXO Cognitive — Trust scoring, sentiment, dissonance."""
|
|
2
|
-
import re
|
|
3
|
-
import numpy as np
|
|
4
|
-
from datetime import datetime, timedelta
|
|
5
|
-
from cognitive._core import _get_db, embed, cosine_similarity, _blob_to_array
|
|
6
|
-
from cognitive._core import POSITIVE_SIGNALS, NEGATIVE_SIGNALS, URGENCY_SIGNALS
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# Trust score events — default deltas (overridable via trust_event_config table)
|
|
10
|
-
_DEFAULT_TRUST_EVENTS = {
|
|
11
|
-
# Positive
|
|
12
|
-
"explicit_thanks": +3,
|
|
13
|
-
"delegation": +2, # user delegates new task without micromanaging
|
|
14
|
-
"paradigm_shift": +2, # user teaches, NEXO learns
|
|
15
|
-
"sibling_detected": +3, # NEXO avoided context error on its own
|
|
16
|
-
"proactive_action": +2, # NEXO did something useful without being asked
|
|
17
|
-
# Negative
|
|
18
|
-
"correction": -3, # user corrects NEXO
|
|
19
|
-
"repeated_error": -7, # Error on something NEXO already had a learning for
|
|
20
|
-
"override": -5, # NEXO's memory was wrong
|
|
21
|
-
"correction_fatigue": -10, # Same memory corrected 3+ times
|
|
22
|
-
"forgot_followup": -4, # Forgot to mark followup or execute it
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
# Lazy-loaded from DB (trust_event_config table overrides defaults)
|
|
26
|
-
_trust_events_cache = None
|
|
27
|
-
_trust_events_cache_ts = 0
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def get_trust_events() -> dict:
|
|
31
|
-
"""Get trust events with deltas. DB overrides take priority over defaults."""
|
|
32
|
-
global _trust_events_cache, _trust_events_cache_ts
|
|
33
|
-
import time
|
|
34
|
-
now = time.time()
|
|
35
|
-
# Cache for 60s to avoid constant DB reads
|
|
36
|
-
if _trust_events_cache is not None and (now - _trust_events_cache_ts) < 60:
|
|
37
|
-
return _trust_events_cache
|
|
38
|
-
|
|
39
|
-
events = dict(_DEFAULT_TRUST_EVENTS)
|
|
40
|
-
try:
|
|
41
|
-
db = _get_db()
|
|
42
|
-
db.execute("""
|
|
43
|
-
CREATE TABLE IF NOT EXISTS trust_event_config (
|
|
44
|
-
event TEXT PRIMARY KEY,
|
|
45
|
-
delta REAL NOT NULL,
|
|
46
|
-
description TEXT DEFAULT '',
|
|
47
|
-
updated_at TEXT DEFAULT (datetime('now'))
|
|
48
|
-
)
|
|
49
|
-
""")
|
|
50
|
-
rows = db.execute("SELECT event, delta FROM trust_event_config").fetchall()
|
|
51
|
-
for r in rows:
|
|
52
|
-
events[r[0]] = r[1]
|
|
53
|
-
except Exception:
|
|
54
|
-
pass
|
|
55
|
-
_trust_events_cache = events
|
|
56
|
-
_trust_events_cache_ts = now
|
|
57
|
-
return events
|
|
58
|
-
|
|
59
|
-
# For backward compat — code that reads TRUST_EVENTS directly
|
|
60
|
-
TRUST_EVENTS = _DEFAULT_TRUST_EVENTS
|
|
61
|
-
|
|
62
|
-
# Auto-detection patterns for trust events from user text
|
|
63
|
-
# Each pattern: (event_name, keywords/phrases that trigger it, min_matches)
|
|
64
|
-
TRUST_AUTO_PATTERNS = {
|
|
65
|
-
"explicit_thanks": {
|
|
66
|
-
"patterns": [
|
|
67
|
-
"gracias", "buen trabajo", "bien hecho", "perfecto", "genial",
|
|
68
|
-
"excelente", "fenomenal", "great job", "nice work", "thank",
|
|
69
|
-
"thanks", "awesome", "amazing", "love it", "me encanta",
|
|
70
|
-
],
|
|
71
|
-
"min_matches": 1,
|
|
72
|
-
},
|
|
73
|
-
"correction": {
|
|
74
|
-
"patterns": [
|
|
75
|
-
"ya te dije", "ya te lo dije", "otra vez", "te he dicho",
|
|
76
|
-
"no es así", "eso no", "mal", "incorrecto", "equivocado",
|
|
77
|
-
"no no no", "that's wrong", "te aviso", "te avisé",
|
|
78
|
-
"2ª vez", "segunda vez", "te lo repito",
|
|
79
|
-
],
|
|
80
|
-
"min_matches": 1,
|
|
81
|
-
},
|
|
82
|
-
"repeated_error": {
|
|
83
|
-
"patterns": [
|
|
84
|
-
"otra vez lo mismo", "siempre igual", "ya te lo dije antes",
|
|
85
|
-
"cuántas veces", "no aprendes", "same mistake", "again the same",
|
|
86
|
-
"ya van", "es la 2", "es la 3", "ya te avisé",
|
|
87
|
-
],
|
|
88
|
-
"min_matches": 1,
|
|
89
|
-
},
|
|
90
|
-
"delegation": {
|
|
91
|
-
"patterns": [
|
|
92
|
-
"encárgate", "hazlo tú", "dale tú", "te lo dejo",
|
|
93
|
-
"manéjalo", "resuélvelo", "handle it", "take care of",
|
|
94
|
-
"you decide", "tú decides", "lo que veas", "como veas",
|
|
95
|
-
],
|
|
96
|
-
"min_matches": 1,
|
|
97
|
-
},
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def auto_detect_trust_events(text: str) -> list[dict]:
|
|
102
|
-
"""Detect trust events from user text. Returns list of {event, delta, reason}.
|
|
103
|
-
|
|
104
|
-
Called automatically by heartbeat. Only fires once per event per heartbeat
|
|
105
|
-
to avoid double-counting.
|
|
106
|
-
"""
|
|
107
|
-
if not text or len(text.strip()) < 5:
|
|
108
|
-
return []
|
|
109
|
-
|
|
110
|
-
text_lower = text.lower()
|
|
111
|
-
events = get_trust_events()
|
|
112
|
-
detected = []
|
|
113
|
-
|
|
114
|
-
for event_name, config in TRUST_AUTO_PATTERNS.items():
|
|
115
|
-
matches = [p for p in config["patterns"] if p in text_lower]
|
|
116
|
-
if len(matches) >= config["min_matches"]:
|
|
117
|
-
delta = events.get(event_name, _DEFAULT_TRUST_EVENTS.get(event_name, 0))
|
|
118
|
-
detected.append({
|
|
119
|
-
"event": event_name,
|
|
120
|
-
"delta": delta,
|
|
121
|
-
"reason": f"auto-detected: {', '.join(matches[:3])}",
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
# Priority: if repeated_error detected, remove correction (it's a superset)
|
|
125
|
-
event_names = {d["event"] for d in detected}
|
|
126
|
-
if "repeated_error" in event_names and "correction" in event_names:
|
|
127
|
-
detected = [d for d in detected if d["event"] != "correction"]
|
|
128
|
-
# If explicit_thanks and delegation both detected, keep both (they're independent)
|
|
129
|
-
|
|
130
|
-
return detected
|
|
131
|
-
|
|
132
|
-
def detect_dissonance(new_instruction: str, min_score: float = 0.65) -> list[dict]:
|
|
133
|
-
"""Detect cognitive dissonance: find LTM memories that contradict a new instruction.
|
|
134
|
-
|
|
135
|
-
When user gives a new instruction that conflicts with established LTM memories
|
|
136
|
-
(strength > 0.8), this function surfaces the conflict so NEXO can verbalize it
|
|
137
|
-
rather than silently obeying or silently resisting.
|
|
138
|
-
|
|
139
|
-
Args:
|
|
140
|
-
new_instruction: The new instruction or preference from user
|
|
141
|
-
min_score: Minimum cosine similarity to consider as potential conflict
|
|
142
|
-
|
|
143
|
-
Returns:
|
|
144
|
-
List of conflicting memories with their strength and content
|
|
145
|
-
"""
|
|
146
|
-
db = _get_db()
|
|
147
|
-
query_vec = embed(new_instruction[:500])
|
|
148
|
-
if np.linalg.norm(query_vec) == 0:
|
|
149
|
-
return []
|
|
150
|
-
|
|
151
|
-
rows = db.execute(
|
|
152
|
-
"SELECT id, content, embedding, source_type, domain, strength, access_count FROM ltm_memories WHERE is_dormant = 0 AND strength > 0.8"
|
|
153
|
-
).fetchall()
|
|
154
|
-
|
|
155
|
-
conflicts = []
|
|
156
|
-
for row in rows:
|
|
157
|
-
vec = _blob_to_array(row["embedding"])
|
|
158
|
-
score = cosine_similarity(query_vec, vec)
|
|
159
|
-
if score >= min_score:
|
|
160
|
-
conflicts.append({
|
|
161
|
-
"memory_id": row["id"],
|
|
162
|
-
"content": row["content"],
|
|
163
|
-
"source_type": row["source_type"],
|
|
164
|
-
"domain": row["domain"],
|
|
165
|
-
"strength": row["strength"],
|
|
166
|
-
"access_count": row["access_count"],
|
|
167
|
-
"similarity": round(score, 3),
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
conflicts.sort(key=lambda x: x["similarity"], reverse=True)
|
|
171
|
-
return conflicts[:5]
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
def resolve_dissonance(memory_id: int, resolution: str, context: str = "") -> str:
|
|
175
|
-
"""Resolve a cognitive dissonance by applying user's decision.
|
|
176
|
-
|
|
177
|
-
Args:
|
|
178
|
-
memory_id: The LTM memory that conflicts with the new instruction
|
|
179
|
-
resolution: One of:
|
|
180
|
-
- 'paradigm_shift': user changed his mind permanently. Decay old memory,
|
|
181
|
-
new instruction becomes the standard.
|
|
182
|
-
- 'exception': This is a one-time override. Keep old memory as standard.
|
|
183
|
-
- 'override': Old memory was wrong. Mark as corrupted and decay to dormant.
|
|
184
|
-
|
|
185
|
-
Returns:
|
|
186
|
-
Status message
|
|
187
|
-
"""
|
|
188
|
-
db = _get_db()
|
|
189
|
-
row = db.execute("SELECT * FROM ltm_memories WHERE id = ?", (memory_id,)).fetchone()
|
|
190
|
-
if not row:
|
|
191
|
-
return f"Memory #{memory_id} not found."
|
|
192
|
-
|
|
193
|
-
now = datetime.utcnow().isoformat()
|
|
194
|
-
|
|
195
|
-
if resolution == "paradigm_shift":
|
|
196
|
-
# Instant decay to 0.3, will naturally fade. New instruction takes over.
|
|
197
|
-
db.execute(
|
|
198
|
-
"UPDATE ltm_memories SET strength = 0.3, last_accessed = ? WHERE id = ?",
|
|
199
|
-
(now, memory_id)
|
|
200
|
-
)
|
|
201
|
-
msg = f"Paradigm shift: Memory #{memory_id} decayed to 0.3. New standard will replace it."
|
|
202
|
-
|
|
203
|
-
elif resolution == "exception":
|
|
204
|
-
# Keep memory as-is, just log the exception
|
|
205
|
-
msg = f"Exception noted: Memory #{memory_id} remains standard. One-time override applied."
|
|
206
|
-
|
|
207
|
-
elif resolution == "override":
|
|
208
|
-
# Memory was wrong — mark as corrupted/dormant
|
|
209
|
-
db.execute(
|
|
210
|
-
"UPDATE ltm_memories SET strength = 0.05, is_dormant = 1, last_accessed = ? WHERE id = ?",
|
|
211
|
-
(now, memory_id)
|
|
212
|
-
)
|
|
213
|
-
msg = f"Override: Memory #{memory_id} marked corrupted and dormant."
|
|
214
|
-
|
|
215
|
-
else:
|
|
216
|
-
return f"Unknown resolution: {resolution}. Use 'paradigm_shift', 'exception', or 'override'."
|
|
217
|
-
|
|
218
|
-
# Log the correction
|
|
219
|
-
db.execute(
|
|
220
|
-
"INSERT INTO memory_corrections (memory_id, store, correction_type, context) VALUES (?, 'ltm', ?, ?)",
|
|
221
|
-
(memory_id, resolution, context[:500])
|
|
222
|
-
)
|
|
223
|
-
db.commit()
|
|
224
|
-
|
|
225
|
-
return msg
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def check_correction_fatigue() -> list[dict]:
|
|
229
|
-
"""Find memories corrected 3+ times in the last 7 days — mark as 'under review'.
|
|
230
|
-
|
|
231
|
-
These memories are unreliable: user keeps overriding them, suggesting
|
|
232
|
-
the memory itself may be wrong or outdated.
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
List of memories that should be flagged as unreliable
|
|
236
|
-
"""
|
|
237
|
-
db = _get_db()
|
|
238
|
-
cutoff = (datetime.utcnow() - timedelta(days=7)).isoformat()
|
|
239
|
-
|
|
240
|
-
rows = db.execute("""
|
|
241
|
-
SELECT memory_id, COUNT(*) as correction_count,
|
|
242
|
-
GROUP_CONCAT(correction_type) as types
|
|
243
|
-
FROM memory_corrections
|
|
244
|
-
WHERE created_at >= ? AND store = 'ltm'
|
|
245
|
-
GROUP BY memory_id
|
|
246
|
-
HAVING COUNT(*) >= 3
|
|
247
|
-
""", (cutoff,)).fetchall()
|
|
248
|
-
|
|
249
|
-
fatigued = []
|
|
250
|
-
for row in rows:
|
|
251
|
-
mem = db.execute(
|
|
252
|
-
"SELECT content, strength, source_type, domain FROM ltm_memories WHERE id = ?",
|
|
253
|
-
(row["memory_id"],)
|
|
254
|
-
).fetchone()
|
|
255
|
-
if mem:
|
|
256
|
-
fatigued.append({
|
|
257
|
-
"memory_id": row["memory_id"],
|
|
258
|
-
"corrections_7d": row["correction_count"],
|
|
259
|
-
"types": row["types"],
|
|
260
|
-
"content": mem["content"][:200],
|
|
261
|
-
"strength": mem["strength"],
|
|
262
|
-
"source_type": mem["source_type"],
|
|
263
|
-
"domain": mem["domain"],
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
# Auto-mark as under review: decay strength to 0.2
|
|
267
|
-
db.execute(
|
|
268
|
-
"UPDATE ltm_memories SET strength = MIN(strength, 0.2), tags = CASE WHEN tags LIKE '%under_review%' THEN tags ELSE tags || ',under_review' END WHERE id = ?",
|
|
269
|
-
(row["memory_id"],)
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
if fatigued:
|
|
273
|
-
db.commit()
|
|
274
|
-
|
|
275
|
-
return fatigued
|
|
276
|
-
|
|
277
|
-
def detect_sentiment(text: str) -> dict:
|
|
278
|
-
"""Analyze user's text for sentiment signals.
|
|
279
|
-
|
|
280
|
-
Returns detected sentiment, intensity, and action guidance for NEXO.
|
|
281
|
-
Not a model — keyword + heuristic based. Fast and deterministic.
|
|
282
|
-
"""
|
|
283
|
-
if not text:
|
|
284
|
-
return {"sentiment": "neutral", "intensity": 0.5, "signals": [], "guidance": ""}
|
|
285
|
-
|
|
286
|
-
text_lower = text.lower()
|
|
287
|
-
words = set(text_lower.split())
|
|
288
|
-
|
|
289
|
-
positive_hits = [s for s in POSITIVE_SIGNALS if s in text_lower]
|
|
290
|
-
negative_hits = [s for s in NEGATIVE_SIGNALS if s in text_lower]
|
|
291
|
-
urgency_hits = [s for s in URGENCY_SIGNALS if s in text_lower]
|
|
292
|
-
|
|
293
|
-
# Heuristics
|
|
294
|
-
is_short = len(text) < 30
|
|
295
|
-
has_caps = any(c.isupper() for c in text[1:]) if len(text) > 1 else False # ignore first char
|
|
296
|
-
has_exclamation = "!" in text
|
|
297
|
-
all_caps_words = sum(1 for w in text.split() if w.isupper() and len(w) > 1)
|
|
298
|
-
|
|
299
|
-
# Score
|
|
300
|
-
pos_score = len(positive_hits)
|
|
301
|
-
neg_score = len(negative_hits)
|
|
302
|
-
|
|
303
|
-
# Caps/short boost negative
|
|
304
|
-
if all_caps_words >= 2:
|
|
305
|
-
neg_score += 2
|
|
306
|
-
if is_short and neg_score > 0:
|
|
307
|
-
neg_score += 1 # Short + negative = terse frustration
|
|
308
|
-
|
|
309
|
-
if urgency_hits:
|
|
310
|
-
neg_score += 1 # Urgency often means something is wrong
|
|
311
|
-
|
|
312
|
-
# Determine sentiment
|
|
313
|
-
if neg_score > pos_score and neg_score >= 1:
|
|
314
|
-
sentiment = "negative"
|
|
315
|
-
intensity = min(1.0, 0.3 + neg_score * 0.15)
|
|
316
|
-
if intensity > 0.7:
|
|
317
|
-
guidance = "MODE: Ultra-concise. Zero explanations. Solve and show result."
|
|
318
|
-
else:
|
|
319
|
-
guidance = "MODE: Concise. Less context, more direct action."
|
|
320
|
-
elif pos_score > neg_score and pos_score >= 1:
|
|
321
|
-
sentiment = "positive"
|
|
322
|
-
intensity = min(1.0, 0.3 + pos_score * 0.15)
|
|
323
|
-
guidance = "MODE: Normal. Good time to suggest backlog ideas or improvements."
|
|
324
|
-
elif urgency_hits:
|
|
325
|
-
sentiment = "urgent"
|
|
326
|
-
intensity = 0.8
|
|
327
|
-
guidance = "MODE: Immediate action. No preambles."
|
|
328
|
-
else:
|
|
329
|
-
sentiment = "neutral"
|
|
330
|
-
intensity = 0.5
|
|
331
|
-
guidance = ""
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
"sentiment": sentiment,
|
|
335
|
-
"intensity": round(intensity, 2),
|
|
336
|
-
"signals": positive_hits + negative_hits + urgency_hits,
|
|
337
|
-
"guidance": guidance,
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
def log_sentiment(text: str) -> dict:
|
|
342
|
-
"""Detect and log user's sentiment. Returns the detection result."""
|
|
343
|
-
result = detect_sentiment(text)
|
|
344
|
-
if result["sentiment"] != "neutral":
|
|
345
|
-
db = _get_db()
|
|
346
|
-
db.execute(
|
|
347
|
-
"INSERT INTO sentiment_log (sentiment, intensity, signals) VALUES (?, ?, ?)",
|
|
348
|
-
(result["sentiment"], result["intensity"], ",".join(result["signals"]))
|
|
349
|
-
)
|
|
350
|
-
db.commit()
|
|
351
|
-
return result
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def get_trust_score() -> float:
|
|
355
|
-
"""Get current trust score. Starts at 50, range 0-100."""
|
|
356
|
-
db = _get_db()
|
|
357
|
-
row = db.execute("SELECT score FROM trust_score ORDER BY id DESC LIMIT 1").fetchone()
|
|
358
|
-
if row is None:
|
|
359
|
-
# Initialize
|
|
360
|
-
db.execute(
|
|
361
|
-
"INSERT INTO trust_score (score, event, delta, context) VALUES (50, 'init', 0, 'Initial trust score')"
|
|
362
|
-
)
|
|
363
|
-
db.commit()
|
|
364
|
-
return 50.0
|
|
365
|
-
return row[0]
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
def _annotate_adaptive_log(event: str, delta: float):
|
|
369
|
-
"""Retroactively annotate the most recent adaptive_log entry with trust feedback."""
|
|
370
|
-
try:
|
|
371
|
-
from db import get_db
|
|
372
|
-
conn = get_db()
|
|
373
|
-
conn.execute(
|
|
374
|
-
"UPDATE adaptive_log SET feedback_event = ?, feedback_delta = ?, "
|
|
375
|
-
"feedback_ts = datetime('now') "
|
|
376
|
-
"WHERE id = (SELECT id FROM adaptive_log "
|
|
377
|
-
"WHERE feedback_event IS NULL "
|
|
378
|
-
"AND timestamp >= datetime('now', '-5 minutes') "
|
|
379
|
-
"ORDER BY id DESC LIMIT 1)",
|
|
380
|
-
(event, int(delta))
|
|
381
|
-
)
|
|
382
|
-
conn.commit()
|
|
383
|
-
except Exception:
|
|
384
|
-
pass
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
def adjust_trust(event: str, context: str = "", custom_delta: float = None) -> dict:
|
|
388
|
-
"""Adjust trust score based on an event.
|
|
389
|
-
|
|
390
|
-
Args:
|
|
391
|
-
event: Event type from TRUST_EVENTS or custom
|
|
392
|
-
context: Description of what happened
|
|
393
|
-
custom_delta: Override the default point value
|
|
394
|
-
|
|
395
|
-
Returns:
|
|
396
|
-
Dict with old_score, delta, new_score, event
|
|
397
|
-
"""
|
|
398
|
-
db = _get_db()
|
|
399
|
-
old_score = get_trust_score()
|
|
400
|
-
|
|
401
|
-
events = get_trust_events()
|
|
402
|
-
delta = custom_delta if custom_delta is not None else events.get(event, 0)
|
|
403
|
-
if delta == 0 and custom_delta is None:
|
|
404
|
-
return {"old_score": old_score, "delta": 0, "new_score": old_score, "event": event, "error": "unknown event"}
|
|
405
|
-
|
|
406
|
-
new_score = max(0.0, min(100.0, old_score + delta))
|
|
407
|
-
|
|
408
|
-
db.execute(
|
|
409
|
-
"INSERT INTO trust_score (score, event, delta, context) VALUES (?, ?, ?, ?)",
|
|
410
|
-
(new_score, event, delta, context[:500])
|
|
411
|
-
)
|
|
412
|
-
db.commit()
|
|
413
|
-
|
|
414
|
-
# Annotate adaptive log for learned weights
|
|
415
|
-
_annotate_adaptive_log(event, delta)
|
|
416
|
-
|
|
417
|
-
# Somatic event logging for repeated_error events (append-only in nexo.db)
|
|
418
|
-
if event == "repeated_error" and context:
|
|
419
|
-
try:
|
|
420
|
-
from db import get_db as get_nexo_db
|
|
421
|
-
area = context.split(":")[0].strip() if ":" in context else "unknown"
|
|
422
|
-
get_nexo_db().execute(
|
|
423
|
-
"INSERT INTO somatic_events (target, target_type, event_type, delta, source) VALUES (?, ?, ?, ?, ?)",
|
|
424
|
-
(area, "area", "repeated_error", 0.20, f"trust:{event}")
|
|
425
|
-
)
|
|
426
|
-
get_nexo_db().commit()
|
|
427
|
-
except Exception:
|
|
428
|
-
pass
|
|
429
|
-
|
|
430
|
-
return {
|
|
431
|
-
"old_score": round(old_score, 1),
|
|
432
|
-
"delta": delta,
|
|
433
|
-
"new_score": round(new_score, 1),
|
|
434
|
-
"event": event,
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
def get_trust_history(days: int = 7) -> dict:
|
|
439
|
-
"""Get trust score history and sentiment summary."""
|
|
440
|
-
db = _get_db()
|
|
441
|
-
cutoff = (datetime.utcnow() - timedelta(days=days)).isoformat()
|
|
442
|
-
|
|
443
|
-
# Trust events
|
|
444
|
-
events = db.execute(
|
|
445
|
-
"SELECT event, delta, score, context, created_at FROM trust_score WHERE created_at >= ? ORDER BY id",
|
|
446
|
-
(cutoff,)
|
|
447
|
-
).fetchall()
|
|
448
|
-
|
|
449
|
-
# Sentiment distribution
|
|
450
|
-
sentiments = db.execute(
|
|
451
|
-
"SELECT sentiment, COUNT(*) as cnt, AVG(intensity) as avg_int FROM sentiment_log WHERE created_at >= ? GROUP BY sentiment",
|
|
452
|
-
(cutoff,)
|
|
453
|
-
).fetchall()
|
|
454
|
-
|
|
455
|
-
current = get_trust_score()
|
|
456
|
-
start_score = events[0]["score"] - events[0]["delta"] if events else current
|
|
457
|
-
|
|
458
|
-
return {
|
|
459
|
-
"current_score": round(current, 1),
|
|
460
|
-
"period_start_score": round(start_score, 1),
|
|
461
|
-
"net_change": round(current - start_score, 1),
|
|
462
|
-
"events": [{"event": e["event"], "delta": e["delta"], "score": round(e["score"], 1), "context": e["context"][:100], "at": e["created_at"]} for e in events],
|
|
463
|
-
"sentiment_distribution": {s["sentiment"]: {"count": s["cnt"], "avg_intensity": round(s["avg_int"], 2)} for s in sentiments},
|
|
464
|
-
}
|
|
Binary file
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "NEXO cron manifest — synced by nexo_update to LaunchAgents (macOS) or systemd timers (Linux)",
|
|
3
|
-
"version": 2,
|
|
4
|
-
"crons": [
|
|
5
|
-
{
|
|
6
|
-
"id": "deep-sleep",
|
|
7
|
-
"script": "scripts/nexo-deep-sleep.sh",
|
|
8
|
-
"type": "shell",
|
|
9
|
-
"schedule": {"hour": 4, "minute": 30},
|
|
10
|
-
"description": "Overnight session analysis — 4 phases: collect, extract, synthesize, apply",
|
|
11
|
-
"core": true
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"id": "sleep",
|
|
15
|
-
"script": "scripts/nexo-sleep.py",
|
|
16
|
-
"schedule": {"hour": 4, "minute": 0},
|
|
17
|
-
"description": "Nightly memory consolidation and dream cycle",
|
|
18
|
-
"core": true
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"id": "cognitive-decay",
|
|
22
|
-
"script": "scripts/nexo-cognitive-decay.py",
|
|
23
|
-
"schedule": {"hour": 3, "minute": 0},
|
|
24
|
-
"description": "Memory decay — reduce strength of unaccessed memories",
|
|
25
|
-
"core": true
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": "learning-housekeep",
|
|
29
|
-
"script": "scripts/nexo-learning-housekeep.py",
|
|
30
|
-
"schedule": {"hour": 3, "minute": 15},
|
|
31
|
-
"description": "Archive stale learnings, deduplicate, validate",
|
|
32
|
-
"core": true
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"id": "immune",
|
|
36
|
-
"script": "scripts/nexo-immune.py",
|
|
37
|
-
"interval_seconds": 1800,
|
|
38
|
-
"description": "Health monitor — checks MCP, DB, services, auto-repairs",
|
|
39
|
-
"core": true
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"id": "watchdog",
|
|
43
|
-
"script": "scripts/nexo-watchdog.sh",
|
|
44
|
-
"type": "shell",
|
|
45
|
-
"interval_seconds": 1800,
|
|
46
|
-
"description": "System health checks — snapshots, logs, alerts",
|
|
47
|
-
"core": true
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"id": "self-audit",
|
|
51
|
-
"script": "scripts/nexo-daily-self-audit.py",
|
|
52
|
-
"schedule": {"hour": 7, "minute": 0},
|
|
53
|
-
"description": "Daily self-audit — validates learnings, protocols, drift",
|
|
54
|
-
"core": true
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"id": "postmortem",
|
|
58
|
-
"script": "scripts/nexo-postmortem-consolidator.py",
|
|
59
|
-
"schedule": {"hour": 23, "minute": 30},
|
|
60
|
-
"description": "Consolidate session post-mortems into patterns",
|
|
61
|
-
"core": true
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
"id": "evolution",
|
|
65
|
-
"script": "scripts/nexo-evolution-run.py",
|
|
66
|
-
"schedule": {"hour": 5, "minute": 0, "weekday": 0},
|
|
67
|
-
"description": "Weekly self-improvement cycle — propose and evaluate changes",
|
|
68
|
-
"core": true
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"id": "followup-hygiene",
|
|
72
|
-
"script": "scripts/nexo-followup-hygiene.py",
|
|
73
|
-
"schedule": {"hour": 5, "minute": 0},
|
|
74
|
-
"description": "Clean stale followups, archive completed, validate dates",
|
|
75
|
-
"core": true
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"id": "synthesis",
|
|
79
|
-
"script": "scripts/nexo-synthesis.py",
|
|
80
|
-
"interval_seconds": 7200,
|
|
81
|
-
"description": "Periodic synthesis — cross-reference learnings, decisions, changes",
|
|
82
|
-
"core": true
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"id": "auto-close-sessions",
|
|
86
|
-
"script": "scripts/nexo-auto-close-sessions.py",
|
|
87
|
-
"interval_seconds": 300,
|
|
88
|
-
"description": "Close stale sessions that lost their parent process",
|
|
89
|
-
"core": true
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"id": "github-monitor",
|
|
93
|
-
"script": "scripts/nexo-github-monitor.py",
|
|
94
|
-
"schedule": {"hour": 8, "minute": 0},
|
|
95
|
-
"description": "Monitor GitHub repo — issues, PRs, stars, auto-respond",
|
|
96
|
-
"core": true
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"id": "catchup",
|
|
100
|
-
"script": "scripts/nexo-catchup.py",
|
|
101
|
-
"schedule": {"hour": 8, "minute": 30},
|
|
102
|
-
"description": "Morning catchup briefing for the user",
|
|
103
|
-
"core": true
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
}
|