diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 68875a83..e77495ba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -77,6 +77,13 @@ jobs:
- name: Typecheck
run: npx tsc --noEmit
+ # Errors fail outright. Warnings are ratcheted: the cap is the current
+ # count of accepted warnings (React-Compiler hooks-rule findings demoted
+ # in eslint.config.mjs + exhaustive-deps) — when you fix warnings, lower
+ # the cap to match; never raise it.
+ - name: Lint
+ run: npm run lint -- --max-warnings 163
+
- name: Tests
run: npm test
diff --git a/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx b/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx
index 8cb0c028..d6076bce 100644
--- a/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx
@@ -3,24 +3,15 @@
import { useMemo } from "react";
import { usePageSections } from "../../hooks/usePageSections";
import { PageSectionItem } from "../../contexts/SidebarContext";
+import { route } from "../../lib/routes";
import {
GearIcon,
- NoSymbolIcon,
DocumentTextIcon,
ChartBarIcon,
BuildingOfficeIcon,
ShieldCheckIcon,
} from "../../lib/sidebarIcons";
-// Inline icon (same as MetricsSidebar had)
-function TrendingUpIcon({ className = "w-5 h-5" }: { className?: string }) {
- return (
-
- );
-}
-
// Inline icon for Ops (wrench)
function WrenchIcon({ className = "w-5 h-5" }: { className?: string }) {
return (
@@ -47,29 +38,29 @@ function GlobeIcon({ className = "w-5 h-5" }: { className?: string }) {
export function AdminPageSections() {
const items: PageSectionItem[] = useMemo(() => [
// Tenants
- { id: "management", label: "Tenant Management", href: "/admin/tenants/management", group: "Tenants", groupIcon: GlobalAdmins, TenantAdmins,{" "}
McpUsers). Restoring this row will overwrite the live{" "}
- IsEnabled flag — confirm that the backup row's enable/disable
+ IsEnabled flag — confirm that the backup row's enable/disable
state is what you intend.
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/OpsAlertRulesSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/OpsAlertRulesSection.tsx
index bcff312c..ff6b2ed1 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/OpsAlertRulesSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/OpsAlertRulesSection.tsx
@@ -232,14 +232,6 @@ export function OpsAlertRulesSection({
const enabledRulesCount = rules.filter(r => r.enabled).length;
const enabledProviders = [telegramEnabled, teamsEnabled, slackEnabled].filter(Boolean).length;
- // Get category for a given event type
- const getCategoryForEvent = (eventType: string): string => {
- for (const [cat, types] of Object.entries(OPS_EVENT_TYPES)) {
- if (types.includes(eventType)) return cat;
- }
- return "Unknown";
- };
-
return (
@@ -574,14 +573,14 @@ export function OpsEventsSection({
View session
setSelectedEvent(null)}
className="inline-flex items-center px-3 py-1.5 rounded-md text-xs font-medium bg-orange-100 text-orange-800 hover:bg-orange-200 dark:bg-orange-900/40 dark:text-orange-200 dark:hover:bg-orange-900/60 border border-orange-300 dark:border-orange-700"
>
Block this device
setSelectedEvent(null)}
className="inline-flex items-center px-3 py-1.5 rounded-md text-xs font-medium bg-red-700 text-white hover:bg-red-800 dark:bg-red-700 dark:hover:bg-red-800"
>
diff --git a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
index bfd2c0fb..fa215dc7 100644
--- a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx
@@ -1,6 +1,6 @@
"use client";
-import { Suspense, useCallback, useEffect, useRef, useState } from "react";
+import { Suspense, useEffect, useRef, useState } from "react";
import { useSearchParams } from "next/navigation";
import { api } from "@/lib/api";
import { authenticatedFetch, TokenExpiredError } from "@/lib/authenticatedFetch";
diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx
index d7c4e47e..e1ae5b58 100644
--- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx
@@ -1,7 +1,6 @@
'use client';
import { useEffect, useState, useMemo, useCallback } from 'react';
-import { useRouter } from 'next/navigation';
import { api } from '@/lib/api';
import TruncatedLabel from '@/components/TruncatedLabel';
import { useAuth } from '../../../../contexts/AuthContext';
@@ -138,9 +137,7 @@ function pN(values: number[], percentile: number): number {
// ── Component ──────────────────────────────────────────────────────────────────
export function SectionAgentMetrics() {
- const router = useRouter();
-
- const { getAccessToken, user } = useAuth();
+ const { getAccessToken } = useAuth();
const { addNotification } = useNotifications();
const [loading, setLoading] = useState(true);
@@ -845,8 +842,6 @@ function StatCard({ label, value, detail, color }: { label: string; value: strin
function FootprintBadge({
value,
thresholds,
- unit,
- formatFn,
}: {
value: number;
thresholds: [number, number, number];
diff --git a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx
index ef2a4a69..63068920 100644
--- a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useCallback, useEffect, useMemo, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import { api } from "@/lib/api";
import { authenticatedFetch, TokenExpiredError } from "@/lib/authenticatedFetch";
import { useAdminConfig } from "../../../AdminConfigContext";
diff --git a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/page.tsx b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/page.tsx
index 4ecc1dca..5a597606 100644
--- a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/page.tsx
@@ -139,7 +139,6 @@ function TabButton({
function InFlightTab({
getAccessToken,
setError,
- setSuccessMessage,
}: {
getAccessToken: (forceRefresh?: boolean) => Promise
XPath query to extract values. Examples: /root/element (path),{" "}
- //element (anywhere),{" "}
+ {"//element"} (anywhere),{" "}
/root/item[@attr='value'] (filter),{" "}
/root/element/text() (text content).