84c1262bd6
Split the aggregate ObservabilityPage into three instance-scoped tabs on their respective service pages, replacing the AlertsTab/LinksTab/ MetricsTab stubs. AlertsTab (alertmanager): Alertmanager status line + active-alerts summary (count + by severity) + expandable alert list (AlertItem with severity badge, summary, description, labels, active-since). Empty state when no alerts. LinksTab (grafana): Grafana status line + machine-selector dropdown + GrafanaLinkCards (Node Exporter metrics dashboard, Loki log explorer) generated from instance.config.base_url. Empty states when no base_url or no machine selected. MetricsTab (prometheus): Prometheus status line + Node Exporter targets table with labels badges. Empty state when no targets. All three tabs use the existing observability hooks which are global / first-configured (no service_id param yet). Per-instance scoping by instance.id is a documented follow-up once the hooks gain the parameter (same pattern as JobsTab slice 7). LinksTab does read instance.config.base_url for the specific Grafana deep-link URL. stubs.tsx loses AlertsTab/LinksTab/MetricsTab stubs (only OverviewTab stub remains); index.ts wires the real components. Old ObservabilityPage.tsx stays in the repo (route removed slice 4; file deleted slice 11). Tests: 2 per tab (renders content + empty/error states with mocked hooks). 106 tests pass (+6); lint/build green. Refs openspec/changes/services-as-hub-ia/ (spec R2.4/R8, tasks slice 9).