Retire Patrol specs pinned to presentation the workbench simplified

The finding-links spec asserted Open related links into the retired
standalone routes from the pre-workbench findings list; those cross-link
affordances were removed deliberately with platform-first navigation,
and the monitor-first workbench feeds findings through a different
pipeline its stubs never reach. The run-history breakdown spec pinned
per-run type counts that the workbench simplified to plain totals; the
underlying count-separation contract (truenas_checked distinct from
agent hosts) lives in the investigation context model and is unit
covered there.
This commit is contained in:
rcourtman 2026-07-08 17:23:04 +01:00
parent 476e0bccb8
commit 5f221941c7
2 changed files with 0 additions and 644 deletions

View file

@ -1,376 +0,0 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test as base, expect } from "@playwright/test";
import { createAuthenticatedStorageState } from "./helpers";
import { PATROL_ROUTE } from "./routes";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
type WorkerFixtures = {
authStorageStatePath: string;
};
const SCREENSHOT_PATH = "/tmp/truenas-patrol-finding-links.png";
const test = base.extend<{}, WorkerFixtures>({
storageState: async ({ authStorageStatePath }, use) => {
await use(authStorageStatePath);
},
authStorageStatePath: [
async ({ browser }, use, workerInfo) => {
const storageStatePath = path.resolve(
__dirname,
"..",
"..",
"tmp",
"playwright-auth",
`truenas-patrol-finding-links-${workerInfo.project.name}.json`,
);
fs.mkdirSync(path.dirname(storageStatePath), { recursive: true });
await createAuthenticatedStorageState(browser, storageStatePath);
try {
await use(storageStatePath);
} finally {
fs.rmSync(storageStatePath, { force: true });
}
},
{ scope: "worker" },
],
});
test.describe("TrueNAS patrol finding links", () => {
test.setTimeout(180_000);
test("keeps TrueNAS Patrol findings on canonical surface handoff routes", async ({
page,
}) => {
await page.route("**/api/resources**", async (route) => {
const requestUrl = new URL(route.request().url());
if (requestUrl.pathname !== "/api/resources") {
await route.continue();
return;
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: [
{
id: "truenas-main",
type: "agent",
name: "truenas-main",
displayName: "TrueNAS Main",
platformId: "truenas-main",
platformType: "truenas",
sourceType: "hybrid",
sources: ["agent", "truenas"],
status: "online",
lastSeen: "2026-03-30T10:00:00Z",
canonicalIdentity: {
displayName: "TrueNAS Main",
hostname: "truenas-main",
platformId: "truenas-main",
},
platformData: {
sources: ["agent", "truenas"],
},
},
{
id: "app-container:truenas-main:nextcloud",
type: "app-container",
name: "nextcloud",
displayName: "Nextcloud",
parentId: "truenas-main",
parentName: "TrueNAS Main",
platformId: "truenas-main",
platformType: "truenas",
sourceType: "api",
sources: ["truenas"],
status: "running",
lastSeen: "2026-03-30T10:00:00Z",
platformData: {
sources: ["truenas"],
},
},
],
meta: {
page: 1,
limit: 200,
total: 2,
totalPages: 1,
},
}),
});
});
await page.route("**/api/ai/patrol/status", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
runtime_state: "active",
running: false,
enabled: true,
last_patrol_at: "2026-03-30T09:00:00Z",
last_activity_at: "2026-03-30T10:05:00Z",
next_patrol_at: "2026-03-30T15:00:00Z",
last_duration_ms: 180000,
resources_checked: 42,
findings_count: 2,
error_count: 0,
healthy: false,
interval_ms: 21600000,
fixed_count: 0,
blocked_reason: "",
blocked_at: "",
license_required: false,
license_status: "active",
summary: {
critical: 1,
warning: 1,
watch: 0,
info: 0,
},
}),
});
});
await page.route("**/api/ai/patrol/runs*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([
{
id: "run-truenas-links",
started_at: "2026-03-30T09:00:00Z",
completed_at: "2026-03-30T09:03:00Z",
duration_ms: 180000,
type: "full",
trigger_reason: "scheduled",
resources_checked: 42,
findings_summary: "2 findings",
finding_ids: ["finding-truenas-system", "finding-truenas-app"],
error_count: 0,
status: "warning",
triage_flags: 0,
tool_call_count: 0,
},
]),
});
});
await page.route("**/api/ai/patrol/autonomy", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
autonomy_level: "monitor",
full_mode_unlocked: false,
investigation_budget: 15,
investigation_timeout_sec: 300,
}),
});
});
await page.route("**/api/ai/models", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ models: [] }),
});
});
await page.route("**/api/settings/ai", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
patrol_enabled: true,
patrol_interval_minutes: 360,
patrol_model: "",
model: "",
alert_triggered_analysis: true,
patrol_alert_triggers_enabled: true,
patrol_anomaly_triggers_enabled: true,
patrol_event_triggers_enabled: true,
patrol_auto_fix: false,
auto_fix_model: "",
}),
});
});
await page.route("**/api/ai/unified/findings*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
findings: [
{
id: "finding-truenas-system",
severity: "critical",
category: "availability",
resource_id: "truenas-main",
resource_name: "TrueNAS Main",
resource_type: "agent",
title: "TrueNAS system offline",
description:
"Pulse Patrol detected that the TrueNAS appliance stopped reporting.",
detected_at: "2026-03-30T09:10:00Z",
last_seen_at: "2026-03-30T10:05:00Z",
auto_resolved: false,
times_raised: 1,
suppressed: false,
investigation_attempts: 0,
},
{
id: "finding-truenas-app",
severity: "warning",
category: "reliability",
resource_id: "app-container:truenas-main:nextcloud",
resource_name: "Nextcloud",
resource_type: "app-container",
title: "Nextcloud failed readiness checks",
description:
"Pulse Patrol detected repeated readiness probe failures.",
detected_at: "2026-03-30T09:20:00Z",
last_seen_at: "2026-03-30T10:05:00Z",
auto_resolved: false,
times_raised: 1,
suppressed: false,
investigation_attempts: 0,
},
],
count: 2,
active_count: 2,
}),
});
});
await page.route("**/api/ai/intelligence/correlations*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ correlations: [], count: 0 }),
});
});
await page.route("**/api/ai/intelligence", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
timestamp: "2026-03-30T10:05:00Z",
overall_health: {
score: 71,
grade: "C",
trend: "stable",
factors: [],
prediction: "TrueNAS resources need attention.",
},
findings_count: {
critical: 1,
warning: 1,
watch: 0,
info: 0,
total: 2,
},
predictions_count: 0,
recent_changes_count: 0,
recent_changes: [],
learning: {
resources_with_knowledge: 0,
total_notes: 0,
resources_with_baselines: 0,
patterns_detected: 0,
correlations_learned: 0,
incidents_tracked: 0,
},
}),
});
});
await page.route("**/api/ai/circuit/status", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
state: "closed",
can_patrol: true,
consecutive_failures: 0,
total_successes: 42,
total_failures: 0,
}),
});
});
await page.route("**/api/ai/approvals", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ approvals: [] }),
});
});
await page.route("**/api/ai/remediation/plans", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ plans: [] }),
});
});
await page.goto(PATROL_ROUTE, { waitUntil: "domcontentloaded" });
await expect(page.getByRole("button", { name: "Findings" })).toBeVisible();
await page.getByText("TrueNAS system offline").click();
const systemFinding = page.locator("#finding-finding-truenas-system");
await expect(
systemFinding.getByRole("link", {
name: "Open related infrastructure for TrueNAS Main",
}),
).toHaveAttribute("href", "/infrastructure?resource=truenas-main");
await expect(
systemFinding.getByRole("link", {
name: "Open related workloads for TrueNAS Main",
}),
).toHaveAttribute(
"href",
"/workloads?type=app-container&platform=truenas&agent=truenas-main",
);
await expect(
systemFinding.getByRole("link", {
name: "Open related storage for TrueNAS Main",
}),
).toHaveAttribute("href", "/storage?source=truenas&node=truenas-main");
await expect(
systemFinding.getByRole("link", {
name: "Open related recovery for TrueNAS Main",
}),
).toHaveAttribute("href", "/recovery?platform=truenas&node=truenas-main");
await page.getByText("Nextcloud failed readiness checks").click();
const appFinding = page.locator("#finding-finding-truenas-app");
await expect(
appFinding.getByRole("link", {
name: "Open related infrastructure for Nextcloud",
}),
).toHaveAttribute(
"href",
"/infrastructure?resource=app-container%3Atruenas-main%3Anextcloud",
);
await expect(
appFinding.getByRole("link", {
name: "Open related workloads for Nextcloud",
}),
).toHaveAttribute(
"href",
"/workloads?type=app-container&platform=truenas&agent=truenas-main&resource=app-container%3Atruenas-main%3Anextcloud",
);
await page.screenshot({ path: SCREENSHOT_PATH, fullPage: true });
});
});

View file

@ -1,268 +0,0 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test as base, expect } from "@playwright/test";
import { createAuthenticatedStorageState } from "./helpers";
import { PATROL_ROUTE } from "./routes";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
type WorkerFixtures = {
authStorageStatePath: string;
};
const SCREENSHOT_PATH = "/tmp/truenas-patrol-run-history.png";
const test = base.extend<{}, WorkerFixtures>({
storageState: async ({ authStorageStatePath }, use) => {
await use(authStorageStatePath);
},
authStorageStatePath: [
async ({ browser }, use, workerInfo) => {
const storageStatePath = path.resolve(
__dirname,
"..",
"..",
"tmp",
"playwright-auth",
`truenas-patrol-history-breakdown-${workerInfo.project.name}.json`,
);
fs.mkdirSync(path.dirname(storageStatePath), { recursive: true });
await createAuthenticatedStorageState(browser, storageStatePath);
try {
await use(storageStatePath);
} finally {
fs.rmSync(storageStatePath, { force: true });
}
},
{ scope: "worker" },
],
});
test.describe("TrueNAS patrol run history", () => {
test.setTimeout(180_000);
test("keeps TrueNAS patrol counts separate from agent hosts in run history", async ({
page,
}) => {
await page.route("**/api/resources**", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: [],
meta: { page: 1, limit: 200, total: 0, totalPages: 0 },
}),
});
});
await page.route("**/api/ai/patrol/status", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
runtime_state: "active",
running: false,
enabled: true,
last_patrol_at: "2026-03-30T09:00:00Z",
last_activity_at: "2026-03-30T09:03:00Z",
next_patrol_at: "2026-03-30T15:00:00Z",
last_duration_ms: 180000,
resources_checked: 2,
findings_count: 0,
error_count: 0,
healthy: true,
interval_ms: 21600000,
fixed_count: 0,
blocked_reason: "",
blocked_at: "",
license_required: false,
license_status: "active",
summary: {
critical: 0,
warning: 0,
watch: 0,
info: 0,
},
}),
});
});
await page.route("**/api/ai/patrol/runs*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([
{
id: "run-truenas-breakdown",
started_at: "2026-03-30T09:00:00Z",
completed_at: "2026-03-30T09:03:00Z",
duration_ms: 180000,
type: "full",
trigger_reason: "scheduled",
resources_checked: 2,
nodes_checked: 0,
guests_checked: 0,
docker_checked: 1,
storage_checked: 0,
hosts_checked: 0,
truenas_checked: 1,
pbs_checked: 0,
pmg_checked: 0,
kubernetes_checked: 0,
new_findings: 0,
existing_findings: 0,
rejected_findings: 0,
resolved_findings: 0,
auto_fix_count: 0,
findings_summary: "TrueNAS patrol complete",
finding_ids: [],
error_count: 0,
status: "healthy",
triage_flags: 0,
tool_call_count: 0,
},
]),
});
});
await page.route("**/api/ai/patrol/autonomy", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
autonomy_level: "monitor",
full_mode_unlocked: false,
investigation_budget: 15,
investigation_timeout_sec: 300,
}),
});
});
await page.route("**/api/ai/models", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ models: [] }),
});
});
await page.route("**/api/settings/ai", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
patrol_enabled: true,
patrol_interval_minutes: 360,
patrol_model: "",
model: "",
alert_triggered_analysis: true,
patrol_alert_triggers_enabled: true,
patrol_anomaly_triggers_enabled: true,
patrol_event_triggers_enabled: true,
patrol_auto_fix: false,
auto_fix_model: "",
}),
});
});
await page.route("**/api/ai/unified/findings*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
findings: [],
count: 0,
active_count: 0,
}),
});
});
await page.route("**/api/ai/intelligence/correlations*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ correlations: [], count: 0 }),
});
});
await page.route("**/api/ai/intelligence", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
timestamp: "2026-03-30T09:03:00Z",
overall_health: {
score: 100,
grade: "A",
trend: "stable",
factors: [],
prediction:
"Infrastructure is healthy with no significant issues detected.",
},
findings_count: {
critical: 0,
warning: 0,
watch: 0,
info: 0,
total: 0,
},
predictions_count: 0,
recent_changes_count: 0,
recent_changes: [],
learning: {
resources_with_knowledge: 0,
total_notes: 0,
resources_with_baselines: 0,
patterns_detected: 0,
correlations_learned: 0,
incidents_tracked: 0,
},
}),
});
});
await page.route("**/api/ai/circuit/status", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
state: "closed",
can_patrol: true,
consecutive_failures: 0,
total_successes: 1,
total_failures: 0,
}),
});
});
await page.route("**/api/ai/approvals", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ approvals: [] }),
});
});
await page.route("**/api/ai/remediation/plans", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ plans: [] }),
});
});
await page.goto(PATROL_ROUTE, { waitUntil: "domcontentloaded" });
await expect(page.getByRole("button", { name: "Findings" })).toBeVisible();
await page.getByRole("button", { name: "Runs" }).click();
await page.getByRole("button", { name: /Checked 2 resources/i }).click();
await expect(page.getByText("1 container")).toBeVisible();
await expect(page.getByText("1 TrueNAS system")).toBeVisible();
await expect(page.getByText(/1 agent/)).toHaveCount(0);
await page.screenshot({ path: SCREENSHOT_PATH, fullPage: true });
});
});