nexo-brain 5.3.20 → 5.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/src/auto_update.py +11 -8
- package/src/dashboard/static/favicon 2.svg +32 -0
- package/src/dashboard/static/nexo-logo 2.png +0 -0
- package/src/dashboard/static/nexo-logo 2.svg +40 -0
- package/src/dashboard/static/style 2.css +2458 -0
- package/src/dashboard/templates/adaptive 2.html +118 -0
- package/src/dashboard/templates/artifacts 2.html +133 -0
- package/src/dashboard/templates/backups 2.html +136 -0
- package/src/dashboard/templates/base 2.html +417 -0
- package/src/dashboard/templates/calendar 2.html +591 -0
- package/src/dashboard/templates/chat 2.html +356 -0
- package/src/dashboard/templates/claims 2.html +259 -0
- package/src/dashboard/templates/cortex 2.html +321 -0
- package/src/dashboard/templates/credentials 2.html +128 -0
- package/src/dashboard/templates/crons 2.html +370 -0
- package/src/dashboard/templates/dashboard 2.html +494 -0
- package/src/dashboard/templates/dreams 2.html +252 -0
- package/src/dashboard/templates/email 2.html +160 -0
- package/src/dashboard/templates/evolution 2.html +189 -0
- package/src/dashboard/templates/feed 2.html +249 -0
- package/src/dashboard/templates/followup_health 2.html +170 -0
- package/src/dashboard/templates/graph 2.html +201 -0
- package/src/dashboard/templates/guard 2.html +259 -0
- package/src/dashboard/templates/inbox 2.html +251 -0
- package/src/dashboard/templates/memory 2.html +420 -0
- package/src/dashboard/templates/operations 2.html +608 -0
- package/src/dashboard/templates/plugins 2.html +185 -0
- package/src/dashboard/templates/protocol 2.html +199 -0
- package/src/dashboard/templates/rules 2.html +246 -0
- package/src/dashboard/templates/sentiment 2.html +247 -0
- package/src/dashboard/templates/sessions 2.html +218 -0
- package/src/dashboard/templates/skills 2.html +329 -0
- package/src/dashboard/templates/somatic 2.html +73 -0
- package/src/dashboard/templates/triggers 2.html +133 -0
- package/src/dashboard/templates/trust 2.html +360 -0
- package/src/db/__init__ 2.py +259 -0
- package/src/db/_core 2.py +437 -0
- package/src/db/_credentials 2.py +124 -0
- package/src/db/_episodic 2.py +762 -0
- package/src/db/_evolution 2.py +54 -0
- package/src/db/_fts 2.py +406 -0
- package/src/db/_goal_profiles 2.py +376 -0
- package/src/db/_hot_context 2.py +660 -0
- package/src/db/_outcomes 2.py +800 -0
- package/src/db/_personal_scripts 2.py +582 -0
- package/src/db/_sessions 2.py +330 -0
- package/src/db/_tasks 2.py +91 -0
- package/src/db/_watchers 2.py +173 -0
- package/src/doctor/formatters 2.py +52 -0
- package/src/doctor/models 2.py +69 -0
- package/src/doctor/planes 2.py +87 -0
- package/src/doctor/providers/__init__ 2.py +1 -0
- package/src/doctor/providers/deep 2.py +367 -0
- package/src/evolution_cycle 2.py +519 -0
- package/src/hooks/auto_capture 2.py +208 -0
- package/src/hooks/caffeinate-guard 2.sh +8 -0
- package/src/hooks/capture-session 2.sh +21 -0
- package/src/hooks/capture-tool-logs 2.sh +158 -0
- package/src/hooks/daily-briefing-check 2.sh +33 -0
- package/src/hooks/heartbeat-enforcement 2.py +90 -0
- package/src/hooks/heartbeat-posttool 2.sh +18 -0
- package/src/hooks/inbox-hook 2.sh +76 -0
- package/src/hooks/post-compact 2.sh +152 -0
- package/src/hooks/pre-compact 2.sh +169 -0
- package/src/hooks/protocol-guardrail 2.sh +10 -0
- package/src/hooks/protocol-pretool-guardrail 2.sh +9 -0
- package/src/hooks/session-stop 2.sh +52 -0
- package/src/kg_populate 2.py +292 -0
- package/src/maintenance 2.py +53 -0
- package/src/memory_backends 2.py +71 -0
- package/src/migrate_embeddings 2.py +124 -0
- package/src/nexo_sdk 2.py +103 -0
- package/src/observability 2.py +199 -0
- package/src/plugin_loader 2.py +217 -0
- package/src/plugins/__init__ 2.py +0 -0
- package/src/plugins/artifact_registry 2.py +450 -0
- package/src/plugins/backup 2.py +127 -0
- package/src/plugins/claims_tools 2.py +119 -0
- package/src/plugins/cognitive_memory 2.py +609 -0
- package/src/plugins/core_rules 2.py +252 -0
- package/src/plugins/cortex 2.py +1155 -0
- package/src/plugins/entities 2.py +67 -0
- package/src/plugins/episodic_memory 2.py +560 -0
- package/src/plugins/evolution 2.py +167 -0
- package/src/plugins/goal_engine 2.py +142 -0
- package/src/plugins/guard 2.py +862 -0
- package/src/plugins/impact 2.py +29 -0
- package/src/plugins/knowledge_graph_tools 2.py +137 -0
- package/src/plugins/media_memory_tools 2.py +98 -0
- package/src/plugins/memory_export 2.py +196 -0
- package/src/plugins/outcomes 2.py +130 -0
- package/src/plugins/personal_scripts 2.py +117 -0
- package/src/plugins/preferences 2.py +47 -0
- package/src/plugins/protocol 2.py +1449 -0
- package/src/plugins/simple_api 2.py +106 -0
- package/src/plugins/skills 2.py +341 -0
- package/src/plugins/state_watchers 2.py +79 -0
- package/src/plugins/update 2.py +986 -0
- package/src/plugins/user_state_tools 2.py +43 -0
- package/src/plugins/workflow 2.py +588 -0
- package/src/protocol_settings 2.py +59 -0
- package/src/public_contribution 2.py +466 -0
- package/src/public_evolution_queue 2.py +241 -0
- package/src/requirements 2.txt +14 -0
- package/src/retroactive_learnings 2.py +373 -0
- package/src/rules/__init__ 2.py +0 -0
- package/src/rules/core-rules 2.json +331 -0
- package/src/rules/migrate 2.py +207 -0
- package/src/runtime_power 2.py +874 -0
- package/src/script_registry 2.py +1559 -0
- package/src/scripts/check-context 2.py +272 -0
- package/src/scripts/deep-sleep/apply_findings 2.py +2327 -0
- package/src/scripts/deep-sleep/collect 2.py +928 -0
- package/src/scripts/deep-sleep/extract 2.py +330 -0
- package/src/scripts/deep-sleep/extract-prompt 2.md +285 -0
- package/src/scripts/deep-sleep/synthesize 2.py +312 -0
- package/src/scripts/deep-sleep/synthesize-prompt 2.md +336 -0
- package/src/scripts/nexo-agent-run 2.py +75 -0
- package/src/scripts/nexo-auto-update 2.py +6 -0
- package/src/scripts/nexo-backup 2.sh +25 -0
- package/src/scripts/nexo-brain-activation 2.sh +140 -0
- package/src/scripts/nexo-catchup 2.py +300 -0
- package/src/scripts/nexo-cognitive-decay 2.py +257 -0
- package/src/scripts/nexo-cortex-cycle 2.py +293 -0
- package/src/scripts/nexo-cron-wrapper 2.sh +53 -0
- package/src/scripts/nexo-daily-self-audit 2.py +2161 -0
- package/src/scripts/nexo-dashboard 2.sh +29 -0
- package/src/scripts/nexo-deep-sleep 2.sh +86 -0
- package/src/scripts/nexo-evolution-run 2.py +1664 -0
- package/src/scripts/nexo-followup-hygiene 2.py +139 -0
- package/src/scripts/nexo-hook-record 2.py +42 -0
- package/src/scripts/nexo-immune 2.py +936 -0
- package/src/scripts/nexo-impact-scorer 2.py +117 -0
- package/src/scripts/nexo-inbox-hook 2.sh +74 -0
- package/src/scripts/nexo-install 2.py +6 -0
- package/src/scripts/nexo-learning-housekeep 2.py +401 -0
- package/src/scripts/nexo-learning-validator 2.py +266 -0
- package/src/scripts/nexo-migrate 2.py +260 -0
- package/src/scripts/nexo-outcome-checker 2.py +127 -0
- package/src/scripts/nexo-postmortem-consolidator 2.py +456 -0
- package/src/scripts/nexo-pre-commit 2.py +120 -0
- package/src/scripts/nexo-prevent-sleep 2.sh +35 -0
- package/src/scripts/nexo-proactive-dashboard 2.py +354 -0
- package/src/scripts/nexo-reflection 2.py +256 -0
- package/src/scripts/nexo-runtime-preflight 2.py +274 -0
- package/src/scripts/nexo-sleep 2.py +631 -0
- package/src/scripts/nexo-snapshot-restore 2.sh +35 -0
- package/src/scripts/nexo-sync-clients 2.py +16 -0
- package/src/scripts/nexo-synthesis 2.py +475 -0
- package/src/scripts/nexo-tcc-approve 2.sh +79 -0
- package/src/scripts/nexo-update 2.sh +306 -0
- package/src/scripts/nexo-watchdog 2.sh +1207 -0
- package/src/scripts/nexo-watchdog-smoke 2.py +119 -0
- package/src/scripts/rehydrate_learnings_from_archive 2.py +245 -0
- package/src/server 2.py +1296 -0
- package/src/skills/run-nexo-audit-phase/guide 2.md +43 -0
- package/src/skills/run-nexo-audit-phase/skill 2.json +59 -0
- package/src/skills/run-nexo-core-fix-cycle/guide 2.md +17 -0
- package/src/skills/run-nexo-core-fix-cycle/script 2.py +276 -0
- package/src/skills/run-nexo-core-fix-cycle/skill 2.json +58 -0
- package/src/skills/run-release-final-audit/guide 2.md +16 -0
- package/src/skills/run-release-final-audit/script 2.py +259 -0
- package/src/skills/run-release-final-audit/skill 2.json +77 -0
- package/src/skills/run-runtime-doctor/guide 2.md +12 -0
- package/src/skills/run-runtime-doctor/script 2.py +21 -0
- package/src/skills/run-runtime-doctor/skill 2.json +25 -0
- package/src/skills_runtime 2.py +932 -0
- package/src/state_watchers_runtime 2.py +475 -0
- package/src/storage_router 2.py +32 -0
- package/src/system_catalog 2.py +786 -0
- package/src/tools_coordination 2.py +103 -0
- package/src/tools_credentials 2.py +68 -0
- package/src/tools_drive 2.py +487 -0
- package/src/tools_hot_context 2.py +163 -0
- package/src/tools_learnings 2.py +612 -0
- package/src/tools_menu 2.py +229 -0
- package/src/tools_reminders 2.py +88 -0
- package/src/tools_reminders_crud 2.py +363 -0
- package/src/tools_sessions 2.py +1054 -0
- package/src/tools_system_catalog 2.py +19 -0
- package/src/tools_task_history 2.py +57 -0
- package/src/tools_transcripts 2.py +98 -0
- package/src/transcript_utils 2.py +412 -0
- package/src/user_context 2.py +46 -0
- package/src/user_data_portability 2.py +328 -0
- package/src/user_state_model 2.py +170 -0
- package/templates/CLAUDE.md 2.template +108 -0
- package/templates/CODEX.AGENTS.md 2.template +66 -0
- package/templates/launchagents/README 2.md +132 -0
- package/templates/launchagents/com.nexo.auto-close-sessions 2.plist +39 -0
- package/templates/launchagents/com.nexo.catchup 2.plist +39 -0
- package/templates/launchagents/com.nexo.cognitive-decay 2.plist +40 -0
- package/templates/launchagents/com.nexo.dashboard 2.plist +43 -0
- package/templates/launchagents/com.nexo.deep-sleep 2.plist +43 -0
- package/templates/launchagents/com.nexo.evolution 2.plist +44 -0
- package/templates/launchagents/com.nexo.followup-hygiene 2.plist +45 -0
- package/templates/launchagents/com.nexo.immune 2.plist +41 -0
- package/templates/launchagents/com.nexo.postmortem 2.plist +45 -0
- package/templates/launchagents/com.nexo.self-audit 2.plist +47 -0
- package/templates/launchagents/com.nexo.synthesis 2.plist +45 -0
- package/templates/launchagents/com.nexo.watchdog 2.plist +37 -0
- package/templates/nexo_helper 2.py +301 -0
- package/templates/openclaw 2.json +13 -0
- package/templates/plugin-template 2.py +40 -0
- package/templates/script-template 2.py +59 -0
- package/templates/script-template 2.sh +13 -0
- package/templates/skill-script-template 2.py +48 -0
- package/templates/skill-template 2.md +33 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _is_repo_root(candidate: Path) -> bool:
|
|
13
|
+
return (
|
|
14
|
+
(candidate / "package.json").is_file()
|
|
15
|
+
and (candidate / "release-contracts").is_dir()
|
|
16
|
+
and (candidate / "scripts" / "verify_release_readiness.py").is_file()
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _normalize_candidate(raw: str | Path) -> Path:
|
|
21
|
+
candidate = Path(raw).expanduser().resolve()
|
|
22
|
+
if candidate.is_file():
|
|
23
|
+
candidate = candidate.parent
|
|
24
|
+
if candidate.name == "src" and (candidate / "server.py").is_file():
|
|
25
|
+
candidate = candidate.parent
|
|
26
|
+
return candidate
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _resolve_repo_root_from_atlas() -> Path | None:
|
|
30
|
+
homes = []
|
|
31
|
+
env_home = os.environ.get("NEXO_HOME", "").strip()
|
|
32
|
+
if env_home:
|
|
33
|
+
homes.append(Path(env_home).expanduser())
|
|
34
|
+
homes.extend((Path.home() / ".nexo", Path.home() / "claude"))
|
|
35
|
+
|
|
36
|
+
seen = set()
|
|
37
|
+
for home in homes:
|
|
38
|
+
key = str(home)
|
|
39
|
+
if key in seen:
|
|
40
|
+
continue
|
|
41
|
+
seen.add(key)
|
|
42
|
+
atlas_path = home / "brain" / "project-atlas.json"
|
|
43
|
+
if not atlas_path.is_file():
|
|
44
|
+
continue
|
|
45
|
+
try:
|
|
46
|
+
payload = json.loads(atlas_path.read_text(encoding="utf-8"))
|
|
47
|
+
except json.JSONDecodeError:
|
|
48
|
+
continue
|
|
49
|
+
nexo = payload.get("nexo") if isinstance(payload, dict) else None
|
|
50
|
+
locations = nexo.get("locations") if isinstance(nexo, dict) else None
|
|
51
|
+
source = locations.get("mcp_server", "") if isinstance(locations, dict) else ""
|
|
52
|
+
if not isinstance(source, str) or not source.strip():
|
|
53
|
+
continue
|
|
54
|
+
candidate = _normalize_candidate(source)
|
|
55
|
+
if _is_repo_root(candidate):
|
|
56
|
+
return candidate
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _resolve_repo_root() -> Path:
|
|
61
|
+
env_code = os.environ.get("NEXO_CODE", "").strip()
|
|
62
|
+
if env_code:
|
|
63
|
+
candidate = _normalize_candidate(env_code)
|
|
64
|
+
if _is_repo_root(candidate):
|
|
65
|
+
return candidate
|
|
66
|
+
|
|
67
|
+
cwd = Path.cwd().resolve()
|
|
68
|
+
for candidate in (cwd, *cwd.parents):
|
|
69
|
+
if _is_repo_root(candidate):
|
|
70
|
+
return candidate
|
|
71
|
+
|
|
72
|
+
atlas_repo = _resolve_repo_root_from_atlas()
|
|
73
|
+
if atlas_repo is not None:
|
|
74
|
+
return atlas_repo
|
|
75
|
+
|
|
76
|
+
script_root = _normalize_candidate(Path(__file__).resolve().parents[3])
|
|
77
|
+
if _is_repo_root(script_root):
|
|
78
|
+
return script_root
|
|
79
|
+
return script_root
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
ROOT = _resolve_repo_root()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _package_version() -> str:
|
|
86
|
+
payload = json.loads((ROOT / "package.json").read_text(encoding="utf-8"))
|
|
87
|
+
version = str(payload.get("version", "") or "").strip()
|
|
88
|
+
if not version:
|
|
89
|
+
raise SystemExit("[release-final-audit] package.json missing version")
|
|
90
|
+
return version
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _parse_bool(raw: str, default: bool) -> bool:
|
|
94
|
+
text = (raw or "").strip().lower()
|
|
95
|
+
if not text:
|
|
96
|
+
return default
|
|
97
|
+
if text in {"1", "true", "yes", "on"}:
|
|
98
|
+
return True
|
|
99
|
+
if text in {"0", "false", "no", "off"}:
|
|
100
|
+
return False
|
|
101
|
+
raise SystemExit(f"[release-final-audit] invalid boolean: {raw}")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _resolve_contract(version: str, raw: str) -> Path | None:
|
|
105
|
+
choice = (raw or "auto").strip()
|
|
106
|
+
if not choice or choice.lower() == "auto":
|
|
107
|
+
candidate = ROOT / "release-contracts" / f"v{version}.json"
|
|
108
|
+
if not candidate.is_file():
|
|
109
|
+
raise SystemExit(
|
|
110
|
+
f"[release-final-audit] missing auto contract for v{version}: {candidate}"
|
|
111
|
+
)
|
|
112
|
+
return candidate
|
|
113
|
+
if choice.lower() in {"none", "skip", "off"}:
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
candidate = Path(choice).expanduser()
|
|
117
|
+
if not candidate.is_absolute():
|
|
118
|
+
candidate = (ROOT / candidate).resolve()
|
|
119
|
+
if not candidate.is_file():
|
|
120
|
+
raise SystemExit(f"[release-final-audit] contract not found: {candidate}")
|
|
121
|
+
return candidate
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _resolve_smoke_runner(version: str) -> Path | None:
|
|
125
|
+
parts = version.split(".")
|
|
126
|
+
if len(parts) < 2:
|
|
127
|
+
return None
|
|
128
|
+
candidate = ROOT / "scripts" / f"run_v{parts[0]}_{parts[1]}_smoke.py"
|
|
129
|
+
return candidate if candidate.is_file() else None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _env(nexo_home: str) -> dict[str, str]:
|
|
133
|
+
env = os.environ.copy()
|
|
134
|
+
existing_pythonpath = env.get("PYTHONPATH", "").strip()
|
|
135
|
+
src_path = str(ROOT / "src")
|
|
136
|
+
env["PYTHONPATH"] = (
|
|
137
|
+
f"{src_path}{os.pathsep}{existing_pythonpath}" if existing_pythonpath else src_path
|
|
138
|
+
)
|
|
139
|
+
env["NEXO_CODE"] = src_path
|
|
140
|
+
if nexo_home.strip():
|
|
141
|
+
env["NEXO_HOME"] = str(Path(nexo_home).expanduser())
|
|
142
|
+
return env
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _command_succeeds(cmd: list[str], *, env: dict[str, str]) -> bool:
|
|
146
|
+
result = subprocess.run(
|
|
147
|
+
cmd,
|
|
148
|
+
cwd=ROOT,
|
|
149
|
+
env=env,
|
|
150
|
+
stdout=subprocess.DEVNULL,
|
|
151
|
+
stderr=subprocess.DEVNULL,
|
|
152
|
+
)
|
|
153
|
+
return result.returncode == 0
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _resolve_python(env: dict[str, str]) -> str:
|
|
157
|
+
candidates = []
|
|
158
|
+
override = os.environ.get("NEXO_RELEASE_PYTHON", "").strip()
|
|
159
|
+
if override:
|
|
160
|
+
candidates.append(override)
|
|
161
|
+
|
|
162
|
+
for name in ("python3", "python"):
|
|
163
|
+
path = shutil.which(name)
|
|
164
|
+
if path:
|
|
165
|
+
candidates.append(path)
|
|
166
|
+
|
|
167
|
+
candidates.append(sys.executable)
|
|
168
|
+
|
|
169
|
+
seen = set()
|
|
170
|
+
for candidate in candidates:
|
|
171
|
+
if not candidate or candidate in seen:
|
|
172
|
+
continue
|
|
173
|
+
seen.add(candidate)
|
|
174
|
+
if _command_succeeds([candidate, "-m", "pytest", "--version"], env=env):
|
|
175
|
+
return candidate
|
|
176
|
+
|
|
177
|
+
raise SystemExit(
|
|
178
|
+
"[release-final-audit] no Python interpreter with pytest available. "
|
|
179
|
+
"Set NEXO_RELEASE_PYTHON or install pytest in the active runtime."
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _run(cmd: list[str], *, env: dict[str, str]) -> None:
|
|
184
|
+
print(f"[release-final-audit] $ {' '.join(cmd)}")
|
|
185
|
+
result = subprocess.run(cmd, cwd=ROOT, env=env)
|
|
186
|
+
if result.returncode != 0:
|
|
187
|
+
raise SystemExit(result.returncode)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _looks_like_nexo_home(raw: str) -> bool:
|
|
191
|
+
if not raw.strip():
|
|
192
|
+
return False
|
|
193
|
+
candidate = Path(raw).expanduser()
|
|
194
|
+
return (candidate / "skills-runtime").is_dir() or (candidate / "operations" / "tool-logs").is_dir()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _parse_optional_args(argv: list[str]) -> tuple[str, str, str, str]:
|
|
198
|
+
website_root = argv[5] if len(argv) > 5 else ""
|
|
199
|
+
nexo_home = argv[6] if len(argv) > 6 else ""
|
|
200
|
+
final_closeout = argv[7] if len(argv) > 7 else ""
|
|
201
|
+
protocol_task_id = argv[8] if len(argv) > 8 else ""
|
|
202
|
+
if website_root and not nexo_home and _looks_like_nexo_home(website_root):
|
|
203
|
+
nexo_home, website_root = website_root, ""
|
|
204
|
+
return website_root, nexo_home, final_closeout, protocol_task_id
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main() -> int:
|
|
208
|
+
contract_arg = sys.argv[1] if len(sys.argv) > 1 else "auto"
|
|
209
|
+
require_contract_complete = _parse_bool(sys.argv[2] if len(sys.argv) > 2 else "true", True)
|
|
210
|
+
include_smoke = _parse_bool(sys.argv[3] if len(sys.argv) > 3 else "true", True)
|
|
211
|
+
ci = _parse_bool(sys.argv[4] if len(sys.argv) > 4 else "false", False)
|
|
212
|
+
website_root, nexo_home, final_closeout_raw, protocol_task_id = _parse_optional_args(sys.argv)
|
|
213
|
+
final_closeout = _parse_bool(final_closeout_raw, False)
|
|
214
|
+
|
|
215
|
+
version = _package_version()
|
|
216
|
+
contract_path = _resolve_contract(version, contract_arg)
|
|
217
|
+
env = _env(nexo_home)
|
|
218
|
+
python_bin = _resolve_python(env)
|
|
219
|
+
|
|
220
|
+
print(f"[release-final-audit] version={version}")
|
|
221
|
+
print(f"[release-final-audit] contract={contract_path or 'none'}")
|
|
222
|
+
print(f"[release-final-audit] include_smoke={include_smoke} ci={ci} final_closeout={final_closeout}")
|
|
223
|
+
print(f"[release-final-audit] python={python_bin}")
|
|
224
|
+
if final_closeout and protocol_task_id.strip():
|
|
225
|
+
print(f"[release-final-audit] protocol_task_id={protocol_task_id.strip()}")
|
|
226
|
+
|
|
227
|
+
if include_smoke:
|
|
228
|
+
smoke_runner = _resolve_smoke_runner(version)
|
|
229
|
+
if smoke_runner is None:
|
|
230
|
+
print(f"[release-final-audit] smoke runner skipped for v{version} (not found)")
|
|
231
|
+
else:
|
|
232
|
+
smoke_output = ROOT / "release-contracts" / "smoke" / f"v{version}.json"
|
|
233
|
+
_run([python_bin, str(smoke_runner), "--output", str(smoke_output)], env=env)
|
|
234
|
+
|
|
235
|
+
readiness_cmd = [python_bin, "scripts/verify_release_readiness.py"]
|
|
236
|
+
if ci:
|
|
237
|
+
readiness_cmd.append("--ci")
|
|
238
|
+
if website_root.strip():
|
|
239
|
+
readiness_cmd.extend(["--website-root", website_root.strip()])
|
|
240
|
+
if nexo_home.strip():
|
|
241
|
+
readiness_cmd.extend(["--nexo-home", nexo_home.strip()])
|
|
242
|
+
if contract_path is not None:
|
|
243
|
+
readiness_cmd.extend(["--contract", str(contract_path)])
|
|
244
|
+
if require_contract_complete:
|
|
245
|
+
readiness_cmd.append("--require-contract-complete")
|
|
246
|
+
elif require_contract_complete:
|
|
247
|
+
print("[release-final-audit] require_contract_complete ignored because contract=none")
|
|
248
|
+
if final_closeout:
|
|
249
|
+
readiness_cmd.append("--final-closeout")
|
|
250
|
+
if protocol_task_id.strip():
|
|
251
|
+
readiness_cmd.extend(["--protocol-task-id", protocol_task_id.strip()])
|
|
252
|
+
|
|
253
|
+
_run(readiness_cmd, env=env)
|
|
254
|
+
print("[release-final-audit] OK")
|
|
255
|
+
return 0
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if __name__ == "__main__":
|
|
259
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "SK-RUN-RELEASE-FINAL-AUDIT",
|
|
3
|
+
"name": "Run Release Final Audit",
|
|
4
|
+
"description": "Runs the final release audit for NEXO: smoke when available, release-readiness checks, contract completeness, and optional closeout gates for GitHub Release, npm, runtime update/doctor, and protocol evidence.",
|
|
5
|
+
"level": "published",
|
|
6
|
+
"mode": "hybrid",
|
|
7
|
+
"source_kind": "core",
|
|
8
|
+
"execution_level": "read-only",
|
|
9
|
+
"approval_required": false,
|
|
10
|
+
"tags": ["release", "audit", "readiness", "consistency", "reversibility"],
|
|
11
|
+
"trigger_patterns": [
|
|
12
|
+
"final release audit",
|
|
13
|
+
"release readiness audit",
|
|
14
|
+
"pre-release audit",
|
|
15
|
+
"release closeout audit",
|
|
16
|
+
"auditoria final release",
|
|
17
|
+
"auditoria final publicacion",
|
|
18
|
+
"seguridad reversibilidad consistencia"
|
|
19
|
+
],
|
|
20
|
+
"params_schema": {
|
|
21
|
+
"contract": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"required": false,
|
|
24
|
+
"default": "auto"
|
|
25
|
+
},
|
|
26
|
+
"require_contract_complete": {
|
|
27
|
+
"type": "boolean",
|
|
28
|
+
"required": false,
|
|
29
|
+
"default": true
|
|
30
|
+
},
|
|
31
|
+
"include_smoke": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"required": false,
|
|
34
|
+
"default": true
|
|
35
|
+
},
|
|
36
|
+
"ci": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"required": false,
|
|
39
|
+
"default": false
|
|
40
|
+
},
|
|
41
|
+
"final_closeout": {
|
|
42
|
+
"type": "boolean",
|
|
43
|
+
"required": false,
|
|
44
|
+
"default": false
|
|
45
|
+
},
|
|
46
|
+
"protocol_task_id": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"required": false,
|
|
49
|
+
"default": ""
|
|
50
|
+
},
|
|
51
|
+
"website_root": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"required": false,
|
|
54
|
+
"default": ""
|
|
55
|
+
},
|
|
56
|
+
"nexo_home": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"required": false,
|
|
59
|
+
"default": ""
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"command_template": {
|
|
63
|
+
"argv": [
|
|
64
|
+
"{{file_path}}",
|
|
65
|
+
"{{contract}}",
|
|
66
|
+
"{{require_contract_complete}}",
|
|
67
|
+
"{{include_smoke}}",
|
|
68
|
+
"{{ci}}",
|
|
69
|
+
"{{website_root}}",
|
|
70
|
+
"{{nexo_home}}",
|
|
71
|
+
"{{final_closeout}}",
|
|
72
|
+
"{{protocol_task_id}}"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"executable_entry": "script.py",
|
|
76
|
+
"stable_after_uses": 5
|
|
77
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Run Runtime Doctor
|
|
2
|
+
|
|
3
|
+
Use this skill when you want a fast health snapshot of the running NEXO system.
|
|
4
|
+
|
|
5
|
+
## Steps
|
|
6
|
+
1. Run the runtime doctor for the requested tier.
|
|
7
|
+
2. Review the degraded or critical checks first.
|
|
8
|
+
3. If the report recommends deterministic fixes, decide whether to run them explicitly.
|
|
9
|
+
|
|
10
|
+
## Gotchas
|
|
11
|
+
- A critical watchdog result reflects a real system issue, not just a stale skill.
|
|
12
|
+
- `all` is broader and slower than `runtime`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main() -> int:
|
|
8
|
+
tier = sys.argv[1] if len(sys.argv) > 1 and sys.argv[1] else "runtime"
|
|
9
|
+
nexo_code = os.environ.get("NEXO_CODE", "")
|
|
10
|
+
if not nexo_code:
|
|
11
|
+
print("NEXO_CODE not set", file=sys.stderr)
|
|
12
|
+
return 1
|
|
13
|
+
|
|
14
|
+
cli_py = os.path.join(nexo_code, "cli.py")
|
|
15
|
+
cmd = [sys.executable, cli_py, "doctor", "--tier", tier, "--plane", "runtime_personal", "--json"]
|
|
16
|
+
result = subprocess.run(cmd, text=True)
|
|
17
|
+
return result.returncode
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "SK-RUN-RUNTIME-DOCTOR",
|
|
3
|
+
"name": "Run Runtime Doctor",
|
|
4
|
+
"description": "Runs the NEXO runtime doctor and returns the current health report.",
|
|
5
|
+
"level": "published",
|
|
6
|
+
"mode": "execute",
|
|
7
|
+
"source_kind": "core",
|
|
8
|
+
"execution_level": "read-only",
|
|
9
|
+
"approval_required": false,
|
|
10
|
+
"tags": ["doctor", "diagnostics", "runtime"],
|
|
11
|
+
"trigger_patterns": ["run doctor", "check runtime health", "diagnose nexo"],
|
|
12
|
+
"params_schema": {
|
|
13
|
+
"tier": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": false,
|
|
16
|
+
"default": "runtime",
|
|
17
|
+
"enum": ["boot", "runtime", "deep", "all"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"command_template": {
|
|
21
|
+
"argv": ["{{file_path}}", "{{tier}}"]
|
|
22
|
+
},
|
|
23
|
+
"executable_entry": "script.py",
|
|
24
|
+
"stable_after_uses": 10
|
|
25
|
+
}
|