Neu: - systemd: secondbrain-dashboard.service (Port 8501, autostart) - cron_rules.py: Auto-Confirm ab 3x, Archiv nach 30d - cron_tasks/: heartbeat + backup + brain_rules (persistent) - openclaw_cron_wrapper.py: subprocess-Isolation (kein SessionTakeover) - chat_autosave.py: Auto-Save von Chat + Kontext-Anreicherung Daten: - 18 unbestätigte Engramme bewertet: - 14x CONFIRMED (Fakten/Definitionen korrekt) - 3x ARCHIVIERT (historisch, nicht aktuell) - 1x CONFIRMED (Regel 73624013) - 0 offene unbestätigte Closes Gitea-Issue: #9
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Heartbeat-Task für Second Brain - isoliert, persistent.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from datetime import datetime, timezone
|
|
|
|
BRAIN_DIR = Path("/root/.openclaw/workspace/second-brain")
|
|
sys.path.insert(0, str(BRAIN_DIR))
|
|
|
|
from src.engram import Engram, Grounding
|
|
from src.store import EngramStore
|
|
|
|
def main():
|
|
output_file = os.environ.get("CRON_OUTPUT_FILE", "/tmp/heartbeat_result.json")
|
|
brain_db = os.environ.get("BRAIN_DB", str(BRAIN_DIR / "data" / "brain.sqlite"))
|
|
store = EngramStore(brain_db)
|
|
|
|
egs = store.get_all(limit=50)
|
|
unconfirmed = [eg for eg in egs if not eg.correctness.confirmed and eg.compute_confidence() > 0.5][:5]
|
|
errors = store.search_tag("error", limit=5)
|
|
|
|
result = {
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
"total_engrams": len(egs),
|
|
"unconfirmed_count": len(unconfirmed),
|
|
"error_count": len(errors),
|
|
"has_action": bool(unconfirmed) or len(errors) >= 3,
|
|
"message": None,
|
|
}
|
|
|
|
if unconfirmed:
|
|
contents = "\n".join([f" - {eg.content[:80]}" for eg in unconfirmed])
|
|
result["message"] = f"🧠 Unbestätigte Engramme:\n{contents}"
|
|
elif len(errors) >= 3:
|
|
result["message"] = f"⚠️ {len(errors)} Fehler-Engramme gespeichert."
|
|
|
|
Path(output_file).write_text(json.dumps(result, indent=2))
|
|
print(f"HEARTBEAT: {result['unconfirmed_count']} unconfirmed, {result['error_count']} errors")
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|