nexo-brain 7.26.0 → 7.27.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.26.0",
3
+ "version": "7.27.0",
4
4
  "description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
5
5
  "author": {
6
6
  "name": "NEXO Brain",
package/README.md CHANGED
@@ -18,7 +18,9 @@
18
18
 
19
19
  [Watch the overview video](https://nexo-brain.com/watch/) · [Watch on YouTube](https://www.youtube.com/watch?v=i2lkGhKyVqI) · [Open the infographic](https://nexo-brain.com/assets/nexo-brain-infographic-v5.png)
20
20
 
21
- Version `7.26.0` is the current packaged-runtime line. Minor release over v7.25.6 - provider runtime parity lets Desktop-managed Brain choose Anthropic Claude or OpenAI Codex, keep provider metadata on sessions/automation/crons, and provision the managed Codex runtime from bundled Desktop resources.
21
+ Version `7.27.0` is the current packaged-runtime line. Minor release over v7.26.0 - Codex-side defaults move to verified `gpt-5.5` resonance tiers, managed config healing follows that model family, and Local Memory file-type actions tolerate transient SQLite locks.
22
+
23
+ Previously in `7.26.0`: minor release over v7.25.6 - provider runtime parity lets Desktop-managed Brain choose Anthropic or OpenAI, keep provider metadata on sessions/automation/crons, and provision the managed OpenAI runtime from bundled Desktop resources.
22
24
 
23
25
  Previously in `7.25.6`: patch release over v7.25.5 - existing Local Memory sidecar databases repair legacy root/exclusion columns before source-dependent indexes are created, and core background crons prefer the NEXO-managed Python runtime.
24
26
 
package/bin/nexo-brain.js CHANGED
@@ -115,8 +115,8 @@ const PUBLIC_CONTRIBUTION_UPSTREAM = "wazionapps/nexo";
115
115
  const MODEL_DEFAULTS_PATH = path.join(__dirname, "..", "src", "model_defaults.json");
116
116
  function _loadModelDefaults() {
117
117
  const fallback = {
118
- claude_code: { model: "claude-opus-4-6[1m]", reasoning_effort: "", display_name: "Opus 4.6 with 1M context" },
119
- codex: { model: "gpt-5.4", reasoning_effort: "xhigh", display_name: "GPT-5.4 with max reasoning" },
118
+ claude_code: { model: "claude-opus-4-7[1m]", reasoning_effort: "max", display_name: "Opus 4.7 with 1M context" },
119
+ codex: { model: "gpt-5.5", reasoning_effort: "xhigh", display_name: "GPT-5.5 with max reasoning" },
120
120
  };
121
121
  try {
122
122
  const raw = JSON.parse(fs.readFileSync(MODEL_DEFAULTS_PATH, "utf8"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.26.0",
3
+ "version": "7.27.0",
4
4
  "mcpName": "io.github.wazionapps/nexo",
5
5
  "description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
6
6
  "homepage": "https://nexo-brain.com",
@@ -44,6 +44,7 @@ CLAUDE_LEGACY_MODEL_HINTS = {"opus", "sonnet"}
44
44
  MODEL_PRICING_USD_PER_1M = {
45
45
  # Pricing snapshot used only when the backend does not return explicit cost.
46
46
  # Codex model names map to the current GPT-5 family pricing.
47
+ "gpt-5.5": {"input": 1.25, "cached_input": 0.125, "output": 10.0},
47
48
  "gpt-5.4": {"input": 1.25, "cached_input": 0.125, "output": 10.0},
48
49
  "gpt-5.4-mini": {"input": 0.25, "cached_input": 0.025, "output": 2.0},
49
50
  }
@@ -66,7 +67,8 @@ def _canonical_pricing_model(model: str) -> str:
66
67
  lowered = str(model or "").strip().lower()
67
68
  lowered = lowered.split("[", 1)[0]
68
69
  aliases = {
69
- "gpt-5": "gpt-5.4",
70
+ "gpt-5": "gpt-5.5",
71
+ "gpt-5.5": "gpt-5.5",
70
72
  "gpt-5.4": "gpt-5.4",
71
73
  "gpt-5-mini": "gpt-5.4-mini",
72
74
  "gpt-5.4-mini": "gpt-5.4-mini",
@@ -260,7 +260,7 @@ def call_model_raw(
260
260
  Parameters follow the Fase 2 plan doc 1 spec:
261
261
 
262
262
  prompt — the user-role text (English or the model's default).
263
- tier — resonance tier; default "muy_bajo" → Haiku / gpt-5.4-mini.
263
+ tier — resonance tier; default "muy_bajo" → Haiku / gpt-5.5 low.
264
264
  caller — resonance caller label. Must be registered in
265
265
  resonance_map.SYSTEM_OWNED_CALLERS. Default
266
266
  "enforcer_classifier".
@@ -203,12 +203,15 @@ def _managed_codex_vendor_present(home: Path | None = None) -> bool:
203
203
  managed_prefix / "node_modules" / "@openai" / "codex",
204
204
  )
205
205
  for package_root in package_roots:
206
- vendor_root = package_root / "vendor"
207
- if not vendor_root.exists():
208
- continue
206
+ vendor_roots = [package_root / "vendor"]
207
+ optional_root = package_root / "node_modules" / "@openai"
208
+ if optional_root.is_dir():
209
+ vendor_roots.extend(item / "vendor" for item in optional_root.glob("codex-*"))
210
+ existing_vendor_roots = [item for item in vendor_roots if item.exists()]
209
211
  try:
210
- if any(candidate.is_file() for candidate in vendor_root.rglob("bin/codex*")):
211
- return True
212
+ for vendor_root in existing_vendor_roots:
213
+ if any(candidate.is_file() for candidate in vendor_root.rglob("bin/codex*")):
214
+ return True
212
215
  except Exception:
213
216
  continue
214
217
  return False
@@ -65,10 +65,9 @@ except Exception:
65
65
  }
66
66
 
67
67
  def resolve_client_runtime_profile(client: str, preferences: dict | None = None) -> dict:
68
- _default_model = "claude-opus-4-7[1m]"
69
68
  defaults = {
70
- "claude_code": {"model": _default_model, "reasoning_effort": ""},
71
- "codex": {"model": _default_model, "reasoning_effort": ""},
69
+ "claude_code": {"model": "claude-opus-4-7[1m]", "reasoning_effort": "max"},
70
+ "codex": {"model": "gpt-5.5", "reasoning_effort": "xhigh"},
72
71
  }
73
72
  return dict(defaults.get(client, {}))
74
73
 
@@ -241,6 +240,15 @@ def _brain_bundle_root() -> Path:
241
240
  return Path(__file__).resolve().parents[1]
242
241
 
243
242
 
243
+ def _codex_bundle_dir() -> Path:
244
+ explicit = str(os.environ.get("NEXO_CODEX_BUNDLE_DIR", "")).strip()
245
+ if explicit:
246
+ candidate = Path(explicit).expanduser()
247
+ if candidate.is_dir():
248
+ return candidate
249
+ return _brain_bundle_root() / "codex"
250
+
251
+
244
252
  def _platform_slug() -> str:
245
253
  if sys.platform.startswith("darwin"):
246
254
  os_part = "darwin"
@@ -379,12 +387,15 @@ def _codex_vendor_present(managed_prefix: Path) -> bool:
379
387
  managed_prefix / "node_modules" / "@openai" / "codex",
380
388
  ]
381
389
  for package_root in package_roots:
382
- vendor_root = package_root / "vendor"
383
- if not vendor_root.exists():
384
- continue
390
+ vendor_roots = [package_root / "vendor"]
391
+ optional_root = package_root / "node_modules" / "@openai"
392
+ if optional_root.is_dir():
393
+ vendor_roots.extend(item / "vendor" for item in optional_root.glob("codex-*"))
394
+ existing_vendor_roots = [item for item in vendor_roots if item.exists()]
385
395
  try:
386
- if any(candidate.is_file() for candidate in vendor_root.rglob("bin/codex*")):
387
- return True
396
+ for vendor_root in existing_vendor_roots:
397
+ if any(candidate.is_file() for candidate in vendor_root.rglob("bin/codex*")):
398
+ return True
388
399
  except Exception:
389
400
  continue
390
401
  return False
@@ -659,7 +670,7 @@ def ensure_codex_installed(*, user_home: str | os.PathLike[str] | None = None) -
659
670
  )
660
671
 
661
672
  desktop_node, bundled_npm_cli = _bundled_npm_runtime()
662
- bundle_dir = _brain_bundle_root() / "codex"
673
+ bundle_dir = _codex_bundle_dir()
663
674
  if desktop_managed and not (desktop_node and bundled_npm_cli):
664
675
  vendor_installed = _install_codex_vendor_from_bundle(
665
676
  bundle_dir=bundle_dir,
@@ -946,7 +957,7 @@ def _sync_codex_managed_config(
946
957
  # Heal any pre-existing Claude model written by earlier NEXO versions.
947
958
  existing_model = str(payload.get("model") or "").strip()
948
959
  if existing_model and _looks_like_claude_model(existing_model):
949
- payload["model"] = "gpt-5.4"
960
+ payload["model"] = "gpt-5.5"
950
961
 
951
962
  # Only write a model from the runtime profile into Codex config if it
952
963
  # looks like a Codex/OpenAI model. Claude models are invalid for Codex
@@ -956,7 +967,7 @@ def _sync_codex_managed_config(
956
967
  payload["model"] = profile_model
957
968
  elif profile_model:
958
969
  # Fall back to a known-good Codex default to self-heal.
959
- payload["model"] = "gpt-5.4"
970
+ payload["model"] = "gpt-5.5"
960
971
  if "reasoning_effort" in runtime_profile:
961
972
  payload["model_reasoning_effort"] = runtime_profile.get("reasoning_effort") or ""
962
973
 
@@ -121,7 +121,7 @@ def classify(
121
121
  context: Optional extra context appended to the user message.
122
122
  call_raw: Injection point for tests — defaults to call_model_raw.
123
123
  cache: TTL cache instance. Tests can pass a fresh cache.
124
- tier: Resonance tier. Default "muy_bajo" (Haiku / gpt-5.4-mini).
124
+ tier: Resonance tier. Default "muy_bajo" (Haiku / gpt-5.5 low).
125
125
  tristate: When True, return "yes" / "no" / "unknown" as strings.
126
126
  "unknown" represents the conservative-parse-fallback path
127
127
  which existing bool callers cannot distinguish from a real
@@ -383,18 +383,22 @@ def _effective_file_type_rule(conn, extension: str) -> dict:
383
383
 
384
384
 
385
385
  def list_file_type_rules(*, readonly: bool = True) -> dict:
386
- if not readonly:
386
+ def _list() -> dict:
387
+ if readonly:
388
+ conn = _read_conn()
389
+ try:
390
+ rows = _list_file_type_rules_conn(conn)
391
+ finally:
392
+ _close_read_conn(conn)
393
+ return _shape_file_type_rules(rows)
394
+
387
395
  conn = _conn()
388
396
  seed_core_file_type_rules(conn)
389
397
  conn.commit()
390
398
  rows = _list_file_type_rules_conn(conn)
391
- else:
392
- conn = _read_conn()
393
- try:
394
- rows = _list_file_type_rules_conn(conn)
395
- finally:
396
- _close_read_conn(conn)
397
- return _shape_file_type_rules(rows)
399
+ return _shape_file_type_rules(rows)
400
+
401
+ return _with_sqlite_busy_retry(_list)
398
402
 
399
403
 
400
404
  def _purge_assets_by_extension(conn, extension: str) -> dict:
@@ -406,49 +410,58 @@ def _purge_assets_by_extension(conn, extension: str) -> dict:
406
410
 
407
411
 
408
412
  def set_file_type_rule(extension: str, *, action: str = "extract", source: str = "user", priority: int | None = None, reason: str = "user") -> dict:
409
- conn = _conn()
410
- ext = _normalize_extension(extension)
411
- if not ext:
412
- return {"ok": False, "error": "extension_required"}
413
- normalized_action = _normalize_file_type_action(action)
414
- source_value = _normalize_source(source)
415
- priority_value = int(priority if priority is not None else (82 if normalized_action == "extract" else 20 if normalized_action == "metadata" else 0))
416
- timestamp = now()
417
- conn.execute(
418
- """
419
- INSERT INTO local_index_file_type_rules(extension, action, source, priority, reason, created_at, updated_at)
420
- VALUES (?, ?, ?, ?, ?, ?, ?)
421
- ON CONFLICT(extension, source) DO UPDATE SET
422
- action=excluded.action,
423
- priority=excluded.priority,
424
- reason=excluded.reason,
425
- updated_at=excluded.updated_at
426
- """,
427
- (ext, normalized_action, source_value, priority_value, reason, timestamp, timestamp),
428
- )
429
- cleanup = _purge_assets_by_extension(conn, ext) if normalized_action == "ignore" and source_value == "user" else {"assets": 0}
430
- conn.commit()
431
- log_event("info", "file_type_rule_set", "Local memory file type rule set", extension=ext, action=normalized_action, source=source_value, cleanup=cleanup)
432
- return {"ok": True, "extension": ext, "action": normalized_action, "source": source_value, "priority": priority_value, "cleanup": cleanup}
413
+ def _set() -> dict:
414
+ conn = _conn()
415
+ ext = _normalize_extension(extension)
416
+ if not ext:
417
+ return {"ok": False, "error": "extension_required"}
418
+ normalized_action = _normalize_file_type_action(action)
419
+ source_value = _normalize_source(source)
420
+ priority_value = int(priority if priority is not None else (82 if normalized_action == "extract" else 20 if normalized_action == "metadata" else 0))
421
+ timestamp = now()
422
+ conn.execute(
423
+ """
424
+ INSERT INTO local_index_file_type_rules(extension, action, source, priority, reason, created_at, updated_at)
425
+ VALUES (?, ?, ?, ?, ?, ?, ?)
426
+ ON CONFLICT(extension, source) DO UPDATE SET
427
+ action=excluded.action,
428
+ priority=excluded.priority,
429
+ reason=excluded.reason,
430
+ updated_at=excluded.updated_at
431
+ """,
432
+ (ext, normalized_action, source_value, priority_value, reason, timestamp, timestamp),
433
+ )
434
+ cleanup = _purge_assets_by_extension(conn, ext) if normalized_action == "ignore" and source_value == "user" else {"assets": 0}
435
+ conn.commit()
436
+ log_event("info", "file_type_rule_set", "Local memory file type rule set", extension=ext, action=normalized_action, source=source_value, cleanup=cleanup)
437
+ return {"ok": True, "extension": ext, "action": normalized_action, "source": source_value, "priority": priority_value, "cleanup": cleanup}
438
+
439
+ return _with_sqlite_busy_retry(_set)
433
440
 
434
441
 
435
442
  def remove_file_type_rule(extension: str, *, source: str = "user") -> dict:
436
- conn = _conn()
437
- ext = _normalize_extension(extension)
438
- source_value = _normalize_source(source)
439
- conn.execute("DELETE FROM local_index_file_type_rules WHERE extension=? AND source=?", (ext, source_value))
440
- conn.commit()
441
- log_event("info", "file_type_rule_removed", "Local memory file type rule removed", extension=ext, source=source_value)
442
- return {"ok": True, "extension": ext, "source": source_value}
443
+ def _remove() -> dict:
444
+ conn = _conn()
445
+ ext = _normalize_extension(extension)
446
+ source_value = _normalize_source(source)
447
+ conn.execute("DELETE FROM local_index_file_type_rules WHERE extension=? AND source=?", (ext, source_value))
448
+ conn.commit()
449
+ log_event("info", "file_type_rule_removed", "Local memory file type rule removed", extension=ext, source=source_value)
450
+ return {"ok": True, "extension": ext, "source": source_value}
451
+
452
+ return _with_sqlite_busy_retry(_remove)
443
453
 
444
454
 
445
455
  def reset_file_type_rules() -> dict:
446
- conn = _conn()
447
- deleted = int(conn.execute("DELETE FROM local_index_file_type_rules WHERE source='user'").rowcount or 0)
448
- seeded = seed_core_file_type_rules(conn)
449
- conn.commit()
450
- log_event("info", "file_type_rules_reset", "Local memory user file type overrides reset", deleted=deleted)
451
- return {"ok": True, "deleted": deleted, "core_rules": int(seeded.get("rules") or 0), "file_types": list_file_type_rules(readonly=False)}
456
+ def _reset() -> dict:
457
+ conn = _conn()
458
+ deleted = int(conn.execute("DELETE FROM local_index_file_type_rules WHERE source='user'").rowcount or 0)
459
+ seeded = seed_core_file_type_rules(conn)
460
+ conn.commit()
461
+ log_event("info", "file_type_rules_reset", "Local memory user file type overrides reset", deleted=deleted)
462
+ return {"ok": True, "deleted": deleted, "core_rules": int(seeded.get("rules") or 0), "file_types": list_file_type_rules(readonly=False)}
463
+
464
+ return _with_sqlite_busy_retry(_reset)
452
465
 
453
466
 
454
467
  def _file_type_action(conn, path: str | Path) -> str:
@@ -8,10 +8,10 @@
8
8
  "previous_defaults": ["claude-opus-4-6[1m]"]
9
9
  },
10
10
  "codex": {
11
- "model": "gpt-5.4",
11
+ "model": "gpt-5.5",
12
12
  "reasoning_effort": "xhigh",
13
- "display_name": "GPT-5.4 with max reasoning",
14
- "recommendation_version": 1,
15
- "previous_defaults": []
13
+ "display_name": "GPT-5.5 with max reasoning",
14
+ "recommendation_version": 2,
15
+ "previous_defaults": ["gpt-5.4"]
16
16
  }
17
17
  }
@@ -27,11 +27,11 @@ _FALLBACK: dict[str, Any] = {
27
27
  "previous_defaults": ["claude-opus-4-6[1m]"],
28
28
  },
29
29
  "codex": {
30
- "model": "gpt-5.4",
30
+ "model": "gpt-5.5",
31
31
  "reasoning_effort": "xhigh",
32
- "display_name": "GPT-5.4 with max reasoning",
33
- "recommendation_version": 1,
34
- "previous_defaults": [],
32
+ "display_name": "GPT-5.5 with max reasoning",
33
+ "recommendation_version": 2,
34
+ "previous_defaults": ["gpt-5.4"],
35
35
  },
36
36
  }
37
37
 
@@ -2,23 +2,23 @@
2
2
  "tiers": {
3
3
  "maximo": {
4
4
  "claude_code": { "model": "claude-opus-4-7[1m]", "effort": "max" },
5
- "codex": { "model": "gpt-5.4", "effort": "xhigh" }
5
+ "codex": { "model": "gpt-5.5", "effort": "xhigh" }
6
6
  },
7
7
  "alto": {
8
8
  "claude_code": { "model": "claude-opus-4-7[1m]", "effort": "xhigh" },
9
- "codex": { "model": "gpt-5.4", "effort": "high" }
9
+ "codex": { "model": "gpt-5.5", "effort": "high" }
10
10
  },
11
11
  "medio": {
12
12
  "claude_code": { "model": "claude-opus-4-7[1m]", "effort": "high" },
13
- "codex": { "model": "gpt-5.4", "effort": "medium" }
13
+ "codex": { "model": "gpt-5.5", "effort": "medium" }
14
14
  },
15
15
  "bajo": {
16
16
  "claude_code": { "model": "claude-opus-4-7[1m]", "effort": "medium" },
17
- "codex": { "model": "gpt-5.4", "effort": "low" }
17
+ "codex": { "model": "gpt-5.5", "effort": "low" }
18
18
  },
19
19
  "muy_bajo": {
20
20
  "claude_code": { "model": "claude-haiku-4-5-20251001", "effort": "" },
21
- "codex": { "model": "gpt-5.4-mini", "effort": "low" }
21
+ "codex": { "model": "gpt-5.5", "effort": "low" }
22
22
  }
23
23
  },
24
24
  "default_tier": "alto"
@@ -37,7 +37,7 @@ Each plist calls `/usr/bin/python3`. If your Python 3 is elsewhere (e.g. Homebre
37
37
 
38
38
  ### 3. Create required directories
39
39
 
40
- The agents write logs to `{{NEXO_HOME}}/logs/` and `{{NEXO_HOME}}/coordination/`. Create them if they do not exist:
40
+ The agents write logs to `{{NEXO_HOME}}/runtime/logs/` and `{{NEXO_HOME}}/coordination/`. Create them if they do not exist:
41
41
 
42
42
  ```bash
43
43
  mkdir -p "$NEXO_HOME/logs" "$NEXO_HOME/coordination"
@@ -117,7 +117,7 @@ These agents power NEXO's learning and memory systems. Strongly recommended.
117
117
 
118
118
  ## Logs
119
119
 
120
- All agents write stdout and stderr to files under `{{NEXO_HOME}}/logs/` (or `{{NEXO_HOME}}/coordination/` for the session-related ones). Check these first when debugging:
120
+ All agents write stdout and stderr to files under `{{NEXO_HOME}}/runtime/logs/` (or `{{NEXO_HOME}}/coordination/` for the session-related ones). Check these first when debugging:
121
121
 
122
122
  ```bash
123
123
  tail -50 "$NEXO_HOME/logs/watchdog-stdout.log"
@@ -14,7 +14,7 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/usr/bin/python3</string>
17
- <string>{{NEXO_HOME}}/auto_close_sessions.py</string>
17
+ <string>{{NEXO_HOME}}/core/auto_close_sessions.py</string>
18
18
  </array>
19
19
  <key>StartInterval</key>
20
20
  <integer>300</integer>
@@ -14,16 +14,16 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/usr/bin/python3</string>
17
- <string>{{NEXO_HOME}}/scripts/nexo-catchup.py</string>
17
+ <string>{{NEXO_HOME}}/core/scripts/nexo-catchup.py</string>
18
18
  </array>
19
19
  <key>RunAtLoad</key>
20
20
  <true/>
21
21
  <key>StartInterval</key>
22
22
  <integer>900</integer>
23
23
  <key>StandardOutPath</key>
24
- <string>{{NEXO_HOME}}/logs/catchup-stdout.log</string>
24
+ <string>{{NEXO_HOME}}/runtime/logs/catchup-stdout.log</string>
25
25
  <key>StandardErrorPath</key>
26
- <string>{{NEXO_HOME}}/logs/catchup-stderr.log</string>
26
+ <string>{{NEXO_HOME}}/runtime/logs/catchup-stderr.log</string>
27
27
  <key>EnvironmentVariables</key>
28
28
  <dict>
29
29
  <key>HOME</key>
@@ -14,7 +14,7 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/usr/bin/python3</string>
17
- <string>{{NEXO_HOME}}/scripts/nexo-cognitive-decay.py</string>
17
+ <string>{{NEXO_HOME}}/core/scripts/nexo-cognitive-decay.py</string>
18
18
  </array>
19
19
  <key>StartCalendarInterval</key>
20
20
  <dict>
@@ -24,9 +24,9 @@
24
24
  <integer>0</integer>
25
25
  </dict>
26
26
  <key>StandardOutPath</key>
27
- <string>{{NEXO_HOME}}/logs/cognitive-decay-stdout.log</string>
27
+ <string>{{NEXO_HOME}}/runtime/logs/cognitive-decay-stdout.log</string>
28
28
  <key>StandardErrorPath</key>
29
- <string>{{NEXO_HOME}}/logs/cognitive-decay-stderr.log</string>
29
+ <string>{{NEXO_HOME}}/runtime/logs/cognitive-decay-stderr.log</string>
30
30
  <key>RunAtLoad</key>
31
31
  <false/>
32
32
  <key>EnvironmentVariables</key>
@@ -15,7 +15,7 @@
15
15
  <key>ProgramArguments</key>
16
16
  <array>
17
17
  <string>/bin/bash</string>
18
- <string>{{NEXO_HOME}}/scripts/nexo-deep-sleep.sh</string>
18
+ <string>{{NEXO_HOME}}/core/scripts/nexo-deep-sleep.sh</string>
19
19
  </array>
20
20
  <key>StartCalendarInterval</key>
21
21
  <dict>
@@ -25,9 +25,9 @@
25
25
  <integer>30</integer>
26
26
  </dict>
27
27
  <key>StandardOutPath</key>
28
- <string>{{NEXO_HOME}}/logs/deep-sleep-stdout.log</string>
28
+ <string>{{NEXO_HOME}}/runtime/logs/deep-sleep-stdout.log</string>
29
29
  <key>StandardErrorPath</key>
30
- <string>{{NEXO_HOME}}/logs/deep-sleep-stderr.log</string>
30
+ <string>{{NEXO_HOME}}/runtime/logs/deep-sleep-stderr.log</string>
31
31
  <key>EnvironmentVariables</key>
32
32
  <dict>
33
33
  <key>PATH</key>
@@ -14,7 +14,7 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/usr/bin/python3</string>
17
- <string>{{NEXO_HOME}}/scripts/nexo-evolution-run.py</string>
17
+ <string>{{NEXO_HOME}}/core/scripts/nexo-evolution-run.py</string>
18
18
  </array>
19
19
  <key>StartCalendarInterval</key>
20
20
  <dict>
@@ -26,9 +26,9 @@
26
26
  <integer>0</integer>
27
27
  </dict>
28
28
  <key>StandardOutPath</key>
29
- <string>{{NEXO_HOME}}/logs/evolution-stdout.log</string>
29
+ <string>{{NEXO_HOME}}/runtime/logs/evolution-stdout.log</string>
30
30
  <key>StandardErrorPath</key>
31
- <string>{{NEXO_HOME}}/logs/evolution-stderr.log</string>
31
+ <string>{{NEXO_HOME}}/runtime/logs/evolution-stderr.log</string>
32
32
  <key>EnvironmentVariables</key>
33
33
  <dict>
34
34
  <key>HOME</key>
@@ -15,7 +15,7 @@
15
15
  <key>ProgramArguments</key>
16
16
  <array>
17
17
  <string>/usr/bin/python3</string>
18
- <string>{{NEXO_HOME}}/scripts/nexo-followup-hygiene.py</string>
18
+ <string>{{NEXO_HOME}}/core/scripts/nexo-followup-hygiene.py</string>
19
19
  </array>
20
20
  <key>StartCalendarInterval</key>
21
21
  <dict>
@@ -27,9 +27,9 @@
27
27
  <integer>0</integer>
28
28
  </dict>
29
29
  <key>StandardOutPath</key>
30
- <string>{{NEXO_HOME}}/logs/followup-hygiene-stdout.log</string>
30
+ <string>{{NEXO_HOME}}/runtime/logs/followup-hygiene-stdout.log</string>
31
31
  <key>StandardErrorPath</key>
32
- <string>{{NEXO_HOME}}/logs/followup-hygiene-stderr.log</string>
32
+ <string>{{NEXO_HOME}}/runtime/logs/followup-hygiene-stderr.log</string>
33
33
  <key>EnvironmentVariables</key>
34
34
  <dict>
35
35
  <key>HOME</key>
@@ -14,7 +14,7 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/usr/bin/python3</string>
17
- <string>{{NEXO_HOME}}/scripts/nexo-immune.py</string>
17
+ <string>{{NEXO_HOME}}/core/scripts/nexo-immune.py</string>
18
18
  </array>
19
19
 
20
20
  <key>StartInterval</key>
@@ -15,7 +15,7 @@
15
15
  <key>ProgramArguments</key>
16
16
  <array>
17
17
  <string>/usr/bin/python3</string>
18
- <string>{{NEXO_HOME}}/scripts/nexo-postmortem-consolidator.py</string>
18
+ <string>{{NEXO_HOME}}/core/scripts/nexo-postmortem-consolidator.py</string>
19
19
  </array>
20
20
  <key>RunAtLoad</key>
21
21
  <false/>
@@ -27,9 +27,9 @@
27
27
  <integer>30</integer>
28
28
  </dict>
29
29
  <key>StandardOutPath</key>
30
- <string>{{NEXO_HOME}}/logs/postmortem-stdout.log</string>
30
+ <string>{{NEXO_HOME}}/runtime/logs/postmortem-stdout.log</string>
31
31
  <key>StandardErrorPath</key>
32
- <string>{{NEXO_HOME}}/logs/postmortem-stderr.log</string>
32
+ <string>{{NEXO_HOME}}/runtime/logs/postmortem-stderr.log</string>
33
33
  <key>EnvironmentVariables</key>
34
34
  <dict>
35
35
  <key>HOME</key>
@@ -15,7 +15,7 @@
15
15
  <key>ProgramArguments</key>
16
16
  <array>
17
17
  <string>/usr/bin/python3</string>
18
- <string>{{NEXO_HOME}}/scripts/nexo-daily-self-audit.py</string>
18
+ <string>{{NEXO_HOME}}/core/scripts/nexo-daily-self-audit.py</string>
19
19
  </array>
20
20
 
21
21
  <key>StartCalendarInterval</key>
@@ -27,10 +27,10 @@
27
27
  </dict>
28
28
 
29
29
  <key>StandardOutPath</key>
30
- <string>{{NEXO_HOME}}/logs/self-audit-stdout.log</string>
30
+ <string>{{NEXO_HOME}}/runtime/logs/self-audit-stdout.log</string>
31
31
 
32
32
  <key>StandardErrorPath</key>
33
- <string>{{NEXO_HOME}}/logs/self-audit-stderr.log</string>
33
+ <string>{{NEXO_HOME}}/runtime/logs/self-audit-stderr.log</string>
34
34
 
35
35
  <key>EnvironmentVariables</key>
36
36
  <dict>
@@ -15,7 +15,7 @@
15
15
  <key>ProgramArguments</key>
16
16
  <array>
17
17
  <string>/usr/bin/python3</string>
18
- <string>{{NEXO_HOME}}/scripts/nexo-synthesis.py</string>
18
+ <string>{{NEXO_HOME}}/core/scripts/nexo-synthesis.py</string>
19
19
  </array>
20
20
 
21
21
  <key>StartCalendarInterval</key>
@@ -14,16 +14,16 @@
14
14
  <key>ProgramArguments</key>
15
15
  <array>
16
16
  <string>/bin/bash</string>
17
- <string>{{NEXO_HOME}}/scripts/nexo-watchdog.sh</string>
17
+ <string>{{NEXO_HOME}}/core/scripts/nexo-watchdog.sh</string>
18
18
  </array>
19
19
  <key>StartInterval</key>
20
20
  <integer>1800</integer>
21
21
  <key>RunAtLoad</key>
22
22
  <true/>
23
23
  <key>StandardOutPath</key>
24
- <string>{{NEXO_HOME}}/logs/watchdog-stdout.log</string>
24
+ <string>{{NEXO_HOME}}/runtime/logs/watchdog-stdout.log</string>
25
25
  <key>StandardErrorPath</key>
26
- <string>{{NEXO_HOME}}/logs/watchdog-stderr.log</string>
26
+ <string>{{NEXO_HOME}}/runtime/logs/watchdog-stderr.log</string>
27
27
  <key>EnvironmentVariables</key>
28
28
  <dict>
29
29
  <key>PATH</key>