Implement Manticore fully and re-theme

This commit is contained in:
2026-03-11 02:19:08 +00:00
parent da044be68c
commit cbedcd67f6
46 changed files with 3444 additions and 944 deletions

View File

@@ -0,0 +1,96 @@
from __future__ import annotations
import time
from django.core.management.base import BaseCommand
from core.events.behavior import summarize_metrics
from core.events.manticore import get_event_ledger_backend
from core.util import logs
log = logs.get_logger("gia_analysis")
class Command(BaseCommand):
help = "Compute behavioral metrics from Manticore event rows into gia_metrics."
def add_arguments(self, parser):
parser.add_argument("--once", action="store_true", default=False)
parser.add_argument("--user-id", type=int)
parser.add_argument("--person-id")
parser.add_argument("--sleep-seconds", type=float, default=60.0)
parser.add_argument("--window-days", nargs="*", type=int, default=[1, 7, 30, 90])
def _run_cycle(
self,
*,
user_id: int | None = None,
person_id: str = "",
window_days: list[int] | None = None,
) -> int:
backend = get_event_ledger_backend()
now_ms = int(time.time() * 1000)
baseline_since = now_ms - (90 * 86400000)
windows = sorted({max(1, int(value)) for value in list(window_days or [1, 7, 30, 90])})
targets = backend.list_event_targets(user_id=user_id)
if person_id:
targets = [
row
for row in targets
if str(row.get("person_id") or "").strip() == str(person_id).strip()
]
written = 0
for target in targets:
target_user_id = int(target.get("user_id") or 0)
target_person_id = str(target.get("person_id") or "").strip()
if target_user_id <= 0 or not target_person_id:
continue
baseline_rows = backend.fetch_events(
user_id=target_user_id,
person_id=target_person_id,
since_ts=baseline_since,
)
if not baseline_rows:
continue
for window in windows:
since_ts = now_ms - (int(window) * 86400000)
window_rows = [
row
for row in baseline_rows
if int(row.get("ts") or 0) >= since_ts
]
metrics = summarize_metrics(window_rows, baseline_rows)
for metric, values in metrics.items():
backend.upsert_metric(
user_id=target_user_id,
person_id=target_person_id,
window_days=int(window),
metric=metric,
value_ms=int(values.get("value_ms") or 0),
baseline_ms=int(values.get("baseline_ms") or 0),
z_score=float(values.get("z_score") or 0.0),
sample_n=int(values.get("sample_n") or 0),
computed_at=now_ms,
)
written += 1
return written
def handle(self, *args, **options):
once = bool(options.get("once"))
sleep_seconds = max(1.0, float(options.get("sleep_seconds") or 60.0))
user_id = options.get("user_id")
person_id = str(options.get("person_id") or "").strip()
window_days = list(options.get("window_days") or [1, 7, 30, 90])
while True:
written = self._run_cycle(
user_id=user_id,
person_id=person_id,
window_days=window_days,
)
self.stdout.write(f"gia-analysis wrote={written}")
if once:
return
time.sleep(sleep_seconds)