Evolution system: twice-daily agent sweep cron, evolution log, NOC evolution panel

This commit is contained in:
drjones
2026-08-03 23:51:36 -07:00
parent 2e2d497cbd
commit 7201804a31
4 changed files with 132 additions and 2 deletions

View File

@@ -2,3 +2,5 @@
* Running on http://127.0.0.1:5106
Press CTRL+C to quit
127.0.0.1 - - [03/Aug/2026 21:35:50] "GET /health HTTP/1.1" 200 -
127.0.0.1 - - [03/Aug/2026 23:50:58] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [03/Aug/2026 23:50:58] "GET /favicon.ico HTTP/1.1" 404 -

10
core/evolution_log.json Normal file
View File

@@ -0,0 +1,10 @@
[
{
"vertical": "all",
"agent": "hermes",
"feature": "NOC Dashboard v2 deployed",
"details": "Clean premium design with Inter font, per-site cards, metrics, evolution tracking panel",
"status": "completed",
"timestamp": "2026-08-03T23:51:15.624329"
}
]

74
core/evolution_log.py Normal file
View File

@@ -0,0 +1,74 @@
"""
Site Evolution Log — tracks all improvements made by evolution agents.
Appended to by sub-agents, displayed on NOC dashboard.
"""
import json, os
from datetime import datetime
from pathlib import Path
LOG_PATH = Path(os.path.expanduser("~/auto-publisher/core/evolution_log.json"))
def log_evolution(vertical: str, agent: str, feature: str, details: str, status: str = "completed"):
"""Record an evolution event."""
log = []
if LOG_PATH.exists():
log = json.loads(LOG_PATH.read_text())
log.append({
"vertical": vertical,
"agent": agent,
"feature": feature,
"details": details[:500],
"status": status,
"timestamp": datetime.now().isoformat(),
})
# Keep last 200 entries
log = log[-200:]
LOG_PATH.write_text(json.dumps(log, indent=2))
def get_recent_evolutions(limit: int = 20) -> list[dict]:
"""Get recent evolution events."""
if not LOG_PATH.exists():
return []
log = json.loads(LOG_PATH.read_text())
return sorted(log, key=lambda x: x["timestamp"], reverse=True)[:limit]
def get_evolution_stats() -> dict:
"""Aggregate evolution statistics."""
if not LOG_PATH.exists():
return {"total": 0, "by_vertical": {}, "recent": []}
log = json.loads(LOG_PATH.read_text())
by_v = {}
for entry in log:
v = entry["vertical"]
by_v[v] = by_v.get(v, 0) + 1
return {
"total": len(log),
"by_vertical": by_v,
"latest": log[-1]["timestamp"][:19] if log else None,
"recent": [e["feature"] for e in log[-5:]],
}
if __name__ == "__main__":
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("--log", action="store_true")
ap.add_argument("--vertical", type=str, default="all")
ap.add_argument("--feature", type=str, default="test")
ap.add_argument("--details", type=str, default="")
ap.add_argument("--agent", type=str, default="manual")
ap.add_argument("--status", type=str, default="completed")
args = ap.parse_args()
if args.log:
log_evolution(args.vertical, args.agent, args.feature, args.details, args.status)
print(f"Logged: {args.vertical}{args.feature}")
else:
stats = get_evolution_stats()
print(json.dumps(stats, indent=2))