nexo-brain 2.6.20 → 2.7.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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +16 -17
- package/package.json +1 -1
- package/src/agent_runner.py +6 -2
- package/src/cli.py +98 -4
- package/src/client_preferences.py +21 -0
- package/src/dashboard/app.py +124 -0
- package/src/dashboard/templates/dashboard.html +59 -1
- package/src/doctor/providers/runtime.py +181 -0
- package/src/scripts/deep-sleep/apply_findings.py +713 -10
- package/src/scripts/deep-sleep/synthesize-prompt.md +23 -0
- package/src/scripts/deep-sleep/synthesize.py +94 -0
- package/templates/nexo_helper.py +44 -0
|
@@ -6,6 +6,7 @@ import json
|
|
|
6
6
|
import os
|
|
7
7
|
import platform
|
|
8
8
|
import plistlib
|
|
9
|
+
import re
|
|
9
10
|
import subprocess
|
|
10
11
|
import sys
|
|
11
12
|
import time
|
|
@@ -38,6 +39,8 @@ SPECIAL_LAUNCHAGENT_IDS = {"prevent-sleep", "tcc-approve"}
|
|
|
38
39
|
SPECIAL_ENV_NORMALIZE_IDS = SPECIAL_LAUNCHAGENT_IDS
|
|
39
40
|
OPTIONALS_FILE = NEXO_HOME / "config" / "optionals.json"
|
|
40
41
|
SCHEDULE_FILE = NEXO_HOME / "config" / "schedule.json"
|
|
42
|
+
PACKAGE_JSON = NEXO_CODE / "package.json"
|
|
43
|
+
CHANGELOG_FILE = NEXO_CODE / "CHANGELOG.md"
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
def _codex_bootstrap_config_status() -> dict:
|
|
@@ -190,6 +193,7 @@ def _client_assumption_regressions() -> list[str]:
|
|
|
190
193
|
return []
|
|
191
194
|
allowed_claude_projects = {
|
|
192
195
|
(src_root / "scripts" / "deep-sleep" / "collect.py").resolve(),
|
|
196
|
+
Path(__file__).resolve(),
|
|
193
197
|
}
|
|
194
198
|
offenders: list[str] = []
|
|
195
199
|
for path in src_root.rglob("*.py"):
|
|
@@ -224,6 +228,44 @@ def _load_json(path: Path) -> dict:
|
|
|
224
228
|
return json.loads(path.read_text())
|
|
225
229
|
|
|
226
230
|
|
|
231
|
+
def _latest_periodic_summary(kind: str) -> dict | None:
|
|
232
|
+
pattern = f"*-{kind}-summary.json"
|
|
233
|
+
candidates: list[tuple[str, Path]] = []
|
|
234
|
+
for path in (NEXO_HOME / "operations" / "deep-sleep").glob(pattern):
|
|
235
|
+
try:
|
|
236
|
+
payload = json.loads(path.read_text())
|
|
237
|
+
except Exception:
|
|
238
|
+
continue
|
|
239
|
+
label = str(payload.get("label", "") or "")
|
|
240
|
+
if label:
|
|
241
|
+
candidates.append((label, path))
|
|
242
|
+
if not candidates:
|
|
243
|
+
return None
|
|
244
|
+
_, path = sorted(candidates, key=lambda item: item[0])[-1]
|
|
245
|
+
try:
|
|
246
|
+
payload = json.loads(path.read_text())
|
|
247
|
+
except Exception:
|
|
248
|
+
return None
|
|
249
|
+
return payload if isinstance(payload, dict) else None
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _package_version() -> str:
|
|
253
|
+
try:
|
|
254
|
+
payload = json.loads(PACKAGE_JSON.read_text())
|
|
255
|
+
except Exception:
|
|
256
|
+
return ""
|
|
257
|
+
return str(payload.get("version", "") or "").strip()
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _top_changelog_version() -> str:
|
|
261
|
+
try:
|
|
262
|
+
text = CHANGELOG_FILE.read_text(encoding="utf-8")
|
|
263
|
+
except Exception:
|
|
264
|
+
return ""
|
|
265
|
+
match = re.search(r"^## \[([^\]]+)\]", text, flags=re.MULTILINE)
|
|
266
|
+
return match.group(1).strip() if match else ""
|
|
267
|
+
|
|
268
|
+
|
|
227
269
|
def _count_checks(checks) -> int:
|
|
228
270
|
if isinstance(checks, list):
|
|
229
271
|
return len(checks)
|
|
@@ -1529,6 +1571,143 @@ def check_client_assumption_regressions() -> DoctorCheck:
|
|
|
1529
1571
|
)
|
|
1530
1572
|
|
|
1531
1573
|
|
|
1574
|
+
def check_protocol_compliance() -> DoctorCheck:
|
|
1575
|
+
summary = _latest_periodic_summary("weekly")
|
|
1576
|
+
if not summary:
|
|
1577
|
+
return DoctorCheck(
|
|
1578
|
+
id="runtime.protocol_compliance",
|
|
1579
|
+
tier="runtime",
|
|
1580
|
+
status="degraded",
|
|
1581
|
+
severity="warn",
|
|
1582
|
+
summary="No weekly Deep Sleep protocol summary found",
|
|
1583
|
+
repair_plan=[
|
|
1584
|
+
"Run the Deep Sleep pipeline so weekly summaries include protocol compliance again",
|
|
1585
|
+
],
|
|
1586
|
+
escalation_prompt=(
|
|
1587
|
+
"NEXO cannot verify heartbeat / guard_check / change_log compliance because the latest weekly Deep Sleep summary is missing."
|
|
1588
|
+
),
|
|
1589
|
+
)
|
|
1590
|
+
|
|
1591
|
+
protocol = summary.get("protocol_summary") or {}
|
|
1592
|
+
overall = protocol.get("overall_compliance_pct")
|
|
1593
|
+
guard = protocol.get("guard_check") or {}
|
|
1594
|
+
heartbeat = protocol.get("heartbeat") or {}
|
|
1595
|
+
change_log = protocol.get("change_log") or {}
|
|
1596
|
+
evidence = [f"weekly summary: {summary.get('label', 'unknown')}"]
|
|
1597
|
+
if overall is not None:
|
|
1598
|
+
evidence.append(f"overall protocol compliance: {overall:.1f}%")
|
|
1599
|
+
if guard.get("compliance_pct") is not None:
|
|
1600
|
+
evidence.append(
|
|
1601
|
+
f"guard_check: {guard.get('executed', 0)}/{guard.get('required', 0)} ({guard['compliance_pct']:.1f}%)"
|
|
1602
|
+
)
|
|
1603
|
+
if heartbeat.get("compliance_pct") is not None:
|
|
1604
|
+
evidence.append(
|
|
1605
|
+
f"heartbeat with context: {heartbeat.get('with_context', 0)}/{heartbeat.get('total', 0)} ({heartbeat['compliance_pct']:.1f}%)"
|
|
1606
|
+
)
|
|
1607
|
+
if change_log.get("compliance_pct") is not None:
|
|
1608
|
+
evidence.append(
|
|
1609
|
+
f"change_log after edits: {change_log.get('logged', 0)}/{change_log.get('edits', 0)} ({change_log['compliance_pct']:.1f}%)"
|
|
1610
|
+
)
|
|
1611
|
+
|
|
1612
|
+
status = "healthy"
|
|
1613
|
+
severity = "info"
|
|
1614
|
+
repair_plan: list[str] = []
|
|
1615
|
+
if overall is None:
|
|
1616
|
+
status = "degraded"
|
|
1617
|
+
severity = "warn"
|
|
1618
|
+
repair_plan.append("Ensure Deep Sleep extractions keep writing protocol_summary data")
|
|
1619
|
+
elif overall < 45:
|
|
1620
|
+
status = "critical"
|
|
1621
|
+
severity = "error"
|
|
1622
|
+
elif overall < 70:
|
|
1623
|
+
status = "degraded"
|
|
1624
|
+
severity = "warn"
|
|
1625
|
+
|
|
1626
|
+
if status != "healthy":
|
|
1627
|
+
repair_plan.extend(
|
|
1628
|
+
[
|
|
1629
|
+
"Reinforce heartbeat discipline on every user message",
|
|
1630
|
+
"Call nexo_guard_check before production/shared edits",
|
|
1631
|
+
"Record production changes with nexo_change_log after editing",
|
|
1632
|
+
]
|
|
1633
|
+
)
|
|
1634
|
+
|
|
1635
|
+
return DoctorCheck(
|
|
1636
|
+
id="runtime.protocol_compliance",
|
|
1637
|
+
tier="runtime",
|
|
1638
|
+
status=status,
|
|
1639
|
+
severity=severity,
|
|
1640
|
+
summary="Protocol compliance looks healthy" if status == "healthy" else "Protocol compliance needs hardening",
|
|
1641
|
+
evidence=evidence,
|
|
1642
|
+
repair_plan=repair_plan,
|
|
1643
|
+
escalation_prompt=(
|
|
1644
|
+
"Heartbeat / guard_check / change_log discipline is drifting. NEXO is at risk of repeating known errors and hiding change history."
|
|
1645
|
+
) if status != "healthy" else "",
|
|
1646
|
+
)
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
def check_release_artifact_sync() -> DoctorCheck:
|
|
1650
|
+
version = _package_version()
|
|
1651
|
+
changelog_version = _top_changelog_version()
|
|
1652
|
+
evidence = []
|
|
1653
|
+
status = "healthy"
|
|
1654
|
+
severity = "info"
|
|
1655
|
+
repair_plan: list[str] = []
|
|
1656
|
+
|
|
1657
|
+
if version:
|
|
1658
|
+
evidence.append(f"package version: {version}")
|
|
1659
|
+
if changelog_version:
|
|
1660
|
+
evidence.append(f"top changelog version: {changelog_version}")
|
|
1661
|
+
|
|
1662
|
+
if version and changelog_version and version != changelog_version:
|
|
1663
|
+
status = "critical"
|
|
1664
|
+
severity = "error"
|
|
1665
|
+
evidence.append("package/changelog release version mismatch")
|
|
1666
|
+
repair_plan.append("Bump or align CHANGELOG.md before publishing")
|
|
1667
|
+
|
|
1668
|
+
sync_script = NEXO_CODE / "scripts" / "sync_release_artifacts.py"
|
|
1669
|
+
if not sync_script.is_file():
|
|
1670
|
+
status = "critical"
|
|
1671
|
+
severity = "error"
|
|
1672
|
+
evidence.append(f"missing release artifact sync script at {sync_script}")
|
|
1673
|
+
repair_plan.append("Restore scripts/sync_release_artifacts.py")
|
|
1674
|
+
else:
|
|
1675
|
+
try:
|
|
1676
|
+
result = subprocess.run(
|
|
1677
|
+
[sys.executable, str(sync_script), "--check"],
|
|
1678
|
+
cwd=str(NEXO_CODE),
|
|
1679
|
+
capture_output=True,
|
|
1680
|
+
text=True,
|
|
1681
|
+
)
|
|
1682
|
+
except Exception as exc:
|
|
1683
|
+
status = "degraded" if status == "healthy" else status
|
|
1684
|
+
severity = "warn" if severity == "info" else severity
|
|
1685
|
+
evidence.append(f"artifact sync check failed to run: {exc}")
|
|
1686
|
+
repair_plan.append("Run scripts/sync_release_artifacts.py manually and inspect the local environment")
|
|
1687
|
+
else:
|
|
1688
|
+
if result.returncode != 0:
|
|
1689
|
+
status = "degraded" if status == "healthy" else status
|
|
1690
|
+
severity = "warn" if severity == "info" else severity
|
|
1691
|
+
detail = result.stderr.strip() or result.stdout.strip() or "artifact sync check failed"
|
|
1692
|
+
evidence.append(detail.splitlines()[0])
|
|
1693
|
+
repair_plan.append("Run scripts/sync_release_artifacts.py before publishing")
|
|
1694
|
+
else:
|
|
1695
|
+
evidence.append("release artifacts in sync")
|
|
1696
|
+
|
|
1697
|
+
return DoctorCheck(
|
|
1698
|
+
id="runtime.release_artifacts",
|
|
1699
|
+
tier="runtime",
|
|
1700
|
+
status=status,
|
|
1701
|
+
severity=severity,
|
|
1702
|
+
summary="Release artifact discipline OK" if status == "healthy" else "Release artifact discipline needs attention",
|
|
1703
|
+
evidence=evidence,
|
|
1704
|
+
repair_plan=repair_plan,
|
|
1705
|
+
escalation_prompt=(
|
|
1706
|
+
"Release-facing artifacts drifted away from the source version contract. Publishing now risks another hotfix release."
|
|
1707
|
+
) if status != "healthy" else "",
|
|
1708
|
+
)
|
|
1709
|
+
|
|
1710
|
+
|
|
1532
1711
|
def run_runtime_checks(fix: bool = False) -> list[DoctorCheck]:
|
|
1533
1712
|
"""Run all runtime-tier checks. Read-only by default."""
|
|
1534
1713
|
return [
|
|
@@ -1542,6 +1721,8 @@ def run_runtime_checks(fix: bool = False) -> list[DoctorCheck]:
|
|
|
1542
1721
|
check_claude_desktop_shared_brain(),
|
|
1543
1722
|
check_transcript_source_parity(),
|
|
1544
1723
|
check_client_assumption_regressions(),
|
|
1724
|
+
check_protocol_compliance(),
|
|
1725
|
+
check_release_artifact_sync(),
|
|
1545
1726
|
check_launchagent_integrity(fix=fix),
|
|
1546
1727
|
check_personal_script_registry(fix=fix),
|
|
1547
1728
|
check_skill_health(fix=fix),
|