Phase 5: Guardian Mode — continuous awareness + proactive AI alerts

- reactor.py: v5.0.0; guardian_loop() background task scans all agents every
  120s; checks CPU/mem/disk thresholds + agent offline transitions + failed
  services; 10min cooldown per metric to debounce repeat alerts; AI analysis
  of critical findings via Claude; proactive chat injection into conversations
  table; handle_sitrep() generates Iron Man-style full/brief situation reports;
  handle_guardian_config() reads/writes guardian_config table; FastAPI endpoints:
  /guardian/status, /guardian/events, /guardian/events/{id}/ack, /guardian/chat
- arc.php: guardian_status, guardian_events, guardian_ack, guardian_chat actions
- chat.php: Tier 0.9d detects sitrep/situation report/how are things commands
- index.html: GUARDIAN tab in right panel; guardian event list with severity
  badges + AI analysis; ACK / ACK ALL buttons; Guardian badge in bottom bar
  (green/amber/red pulse based on unread critical events); proactive chat
  polling every 30s surfacing guardian-injected messages as JARVIS speech
- admin/index.php: GUARDIAN MODE tab; status bar + events table + config modal;
  inline SITREP runner with result modal; threshold configuration
This commit is contained in:
2026-06-11 04:52:08 +00:00
parent 56c9e2d914
commit f15225994a
4 changed files with 501 additions and 1 deletions
+34
View File
@@ -179,6 +179,40 @@ switch ($action) {
echo json_encode(arc_request('DELETE', "/screenshots/{$id}"));
break;
// ── GUARDIAN MODE ─────────────────────────────────────────────────────────
case 'guardian_status':
echo json_encode(arc_request('GET', '/guardian/status'));
break;
case 'guardian_events':
$limit = (int)($_GET['limit'] ?? 30);
$unread = !empty($_GET['unread']) ? 'true' : '';
$severity = $_GET['severity'] ?? '';
$since = $_GET['since'] ?? '';
$qs = http_build_query(array_filter([
'limit' => $limit,
'unread' => $unread,
'severity' => $severity,
'since' => $since,
]));
echo json_encode(arc_request('GET', '/guardian/events' . ($qs ? "?{$qs}" : '')));
break;
case 'guardian_ack':
$id = (int)($_GET['id'] ?? $data['id'] ?? 0);
if ($id) {
echo json_encode(arc_request('POST', "/guardian/events/{$id}/ack"));
} else {
echo json_encode(arc_request('POST', '/guardian/events/ack_all'));
}
break;
case 'guardian_chat':
$since = $_GET['since'] ?? '';
$qs = $since ? '?since=' . urlencode($since) : '';
echo json_encode(arc_request('GET', '/guardian/chat' . $qs));
break;
default:
http_response_code(404);
echo json_encode(['error' => "Unknown arc action: {$action}"]);
+29
View File
@@ -1190,6 +1190,35 @@ if (!$reply) {
}
}
// ── Tier 0.9d: Guardian Mode — sitrep detection ───────────────────────────
if (!$reply) {
$sitrepPatterns = [
'/^(?:jarvis[,\s]+)?(?:sitrep|sit\s+rep|situation\s+report|status\s+report)/i',
'/^(?:jarvis[,\s]+)?(?:give\s+me\s+a|run\s+a)\s+(?:sitrep|situation|status)\s*(?:report)?/i',
'/^(?:jarvis[,\s]+)?(?:how\s+(?:are|is)\s+(?:everything|all\s+systems?|things?)(?:\s+looking)?)/i',
'/^(?:jarvis[,\s]+)?(?:system\s+health|overall\s+status|all\s+systems\s+(?:check|status|go))/i',
'/^(?:jarvis[,\s]+)?what(?:\'s|\s+is)\s+(?:the\s+)?overall\s+(?:system\s+)?status/i',
];
$isSimple = (bool) preg_match('/\b(?:brief|quick|short|summary)\b/i', $message);
foreach ($sitrepPatterns as $pat) {
if (preg_match($pat, $message)) {
$arcRes = arcSubmitJob('sitrep', [
'detail' => $isSimple ? 'brief' : 'full',
'provider' => 'claude',
], $sessionId);
if (isset($arcRes['job_id'])) {
$arcJobId = $arcRes['job_id'];
$reply = "◈ GUARDIAN PROTOCOL — Generating situation report (Job #{$arcJobId}). Scanning all field stations and synthesizing a briefing now, {$userAddr}. Stand by.";
$source = 'arc:sitrep';
} else {
$reply = "Guardian Protocol is offline, {$userAddr}. Arc Reactor may be unavailable.";
$source = 'arc:offline';
}
break;
}
}
}
// ── Tier 0.9e: Intel Protocol — research & tool_loop detection ────────────
$intelPatterns = [
'/^(?:jarvis[,\s]+)?(?:research|investigate|deep[- ]dive|deep dive)\s+(.+)/i' => 'research',