diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
index bd2fbe8a17..19ee8af773 100644
--- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md
+++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
@@ -8049,12 +8049,14 @@ backend deletion or destination delivery.
### Large platform notices keep the inventory in view
-`PlatformOutdatedAgentNotice` previews at most three affected names and exposes
-the full list through a keyboard-operable button when more hosts are outdated.
-The count, update guidance and action link remain visible. This keeps a
-large-estate stale-agent warning from pushing the platform inventory and
-Storage search below the phone viewport while preserving every affected name
-on demand. The component test pins collapsed, expanded and collapsed-again
+`PlatformOutdatedAgentNotice` is maintenance guidance, not an incident, so it
+renders as one sentence in the info tone: the count, what the update brings,
+a keyboard-operable "Which hosts?" toggle (any count above one) that reveals
+every affected name, and the upgrade link inline in the same line rather than
+on an action row. This keeps the stale-agent notice from pushing the platform
+inventory and Storage search below the fold at desktop and phone widths, and
+from competing with real warnings for attention, while preserving every
+affected name on demand. The component test pins collapsed, expanded and collapsed-again
states; 1440px, 768px and 390px browser checks verify placement and overflow.
The shared `InlineNotice` action text uses opaque 800-level colors for its four
tones. The current Tailwind configuration overrides several 900-level palette
diff --git a/frontend-modern/browser-verification/b7a057ac9a6f4dd8.json b/frontend-modern/browser-verification/b7a057ac9a6f4dd8.json
new file mode 100644
index 0000000000..e2ec2c423c
--- /dev/null
+++ b/frontend-modern/browser-verification/b7a057ac9a6f4dd8.json
@@ -0,0 +1,35 @@
+{
+ "version": 1,
+ "base_sha": "53e2d27ab420c505f54694b0ccbb7d843ff6eded",
+ "verified_at": "2026-10-05T00:02:30Z",
+ "result": "passed",
+ "changed_paths": [
+ "frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx"
+ ],
+ "content_sha256": {
+ "frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx": "b13db44a0fea2de8605bb79a1d1fd011f5023e9c8cba44f465c305eeac4f00b5"
+ },
+ "routes": [
+ "/proxmox/overview",
+ "/docker/overview",
+ "/kubernetes/overview"
+ ],
+ "viewports": [
+ {
+ "width": 1440,
+ "height": 700
+ },
+ {
+ "width": 390,
+ "height": 844
+ }
+ ],
+ "states": [
+ "Mock estate with five Proxmox hosts, three Docker hosts and three Kubernetes nodes on an older agent. Before: a three-line amber warning listing three names plus \"and 2 more\", a Show all button and an action row above every platform tab.",
+ "After at 1440: one info-tone line on Proxmox (5 hosts run an older Pulse agent. Update them to v4.26.0 for the latest agent-contributed Proxmox node detail and command support. Which hosts? Open agent upgrade commands) with the node table directly below.",
+ "Phone 390x844 Kubernetes: the missing-data sentence, Which nodes? toggle and upgrade link wrap within the notice above the clusters table."
+ ],
+ "interactions": [
+ "Loaded each route signed in and inspected screenshots; the component test exercises the Which hosts? toggle expanding and collapsing the affected names and checks the inline link href."
+ ]
+}
diff --git a/frontend-modern/src/features/kubernetes/__tests__/KubernetesPageSurface.contract.test.tsx b/frontend-modern/src/features/kubernetes/__tests__/KubernetesPageSurface.contract.test.tsx
index bceef968f2..08f9a96b48 100644
--- a/frontend-modern/src/features/kubernetes/__tests__/KubernetesPageSurface.contract.test.tsx
+++ b/frontend-modern/src/features/kubernetes/__tests__/KubernetesPageSurface.contract.test.tsx
@@ -257,7 +257,7 @@ describe('KubernetesPageSurface contract', () => {
renderSurface();
const notice = screen.getByTestId('platform-outdated-agent-notice');
- expect(notice).toHaveTextContent('k8s-node-1 is running an older Pulse agent (v5.1.34).');
+ expect(notice).toHaveTextContent('k8s-node-1 runs an older Pulse agent (v5.1.34), so');
expect(notice).toHaveTextContent('Kubernetes nodes, workloads, services, storage');
expect(screen.getByRole('link', { name: 'Open agent upgrade commands' })).toHaveAttribute(
'href',
@@ -300,7 +300,7 @@ describe('KubernetesPageSurface contract', () => {
renderSurface();
const notice = screen.getByTestId('platform-outdated-agent-notice');
- expect(notice).toHaveTextContent('worker-1 is running an older Pulse agent (v5.1.34).');
+ expect(notice).toHaveTextContent('worker-1 runs an older Pulse agent (v5.1.34), so');
expect(notice).toHaveTextContent('for this node');
expect(notice).toHaveTextContent('Kubernetes nodes, workloads, services, storage');
expect(screen.getByRole('link', { name: 'Open agent upgrade commands' })).toHaveAttribute(
diff --git a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
index 5117454821..c0b3a6ca0e 100644
--- a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
+++ b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
@@ -28,7 +28,7 @@ describe('PlatformOutdatedAgentNotice', () => {
));
const notice = screen.getByTestId('platform-outdated-agent-notice');
expect(notice).toHaveTextContent(
- 'tower is running an older Pulse agent (v6.0.0-rc.5). Update it to v6.0.0-rc.6 to see images, networks, and storage for this host.',
+ 'tower runs an older Pulse agent (v6.0.0-rc.5), so images, networks, and storage for this host may be missing.',
);
expect(screen.getByRole('link', { name: 'Open agent upgrade commands' })).toHaveAttribute(
'href',
@@ -36,23 +36,7 @@ describe('PlatformOutdatedAgentNotice', () => {
);
});
- it('summarises multiple outdated hosts and lists them', () => {
- render(() => (
-
- ));
- const notice = screen.getByTestId('platform-outdated-agent-notice');
- expect(notice).toHaveTextContent('2 hosts are running an older Pulse agent.');
- expect(notice).toHaveTextContent('Affected: tower, delly.');
- });
-
- it('keeps a large affected-host list behind an expandable preview', () => {
+ it('summarises multiple outdated hosts in one line and keeps names behind a toggle', () => {
render(() => (
{
{ name: 'remote', version: 'v6.0.0-rc.5' },
]}
targetVersion="v6.0.0-rc.6"
- missingLabel="images"
+ missingLabel="images, networks, and storage"
+ actionHref="/settings/infrastructure"
+ actionLabel="Open agent upgrade commands"
/>
));
const notice = screen.getByTestId('platform-outdated-agent-notice');
- expect(notice).toHaveTextContent('Affected: tower, delly, lab, and 1 more.');
- expect(notice).not.toHaveTextContent('Affected: tower, delly, lab, remote.');
+ expect(notice).toHaveTextContent(
+ '4 hosts run an older Pulse agent, so images, networks, and storage may be missing.',
+ );
+ // Maintenance, not an incident: the info tone, with names on demand.
+ expect(notice.className).toContain('bg-blue-50');
+ expect(notice).not.toHaveTextContent('Affected:');
+ expect(screen.getByRole('link', { name: 'Open agent upgrade commands' })).toHaveAttribute(
+ 'href',
+ '/settings/infrastructure',
+ );
- const toggle = screen.getByRole('button', { name: 'Show all 4 hosts' });
+ const toggle = screen.getByRole('button', { name: 'Which hosts?' });
expect(toggle).toHaveAttribute('aria-expanded', 'false');
fireEvent.click(toggle);
expect(toggle).toHaveAttribute('aria-expanded', 'true');
expect(notice).toHaveTextContent('Affected: tower, delly, lab, remote.');
- fireEvent.click(screen.getByRole('button', { name: 'Hide affected names' }));
- expect(notice).not.toHaveTextContent('Affected: tower, delly, lab, remote.');
+ fireEvent.click(screen.getByRole('button', { name: 'Hide names' }));
+ expect(notice).not.toHaveTextContent('Affected:');
});
it('uses latest-detail copy for hybrid platform pages', () => {
@@ -90,7 +84,7 @@ describe('PlatformOutdatedAgentNotice', () => {
));
expect(screen.getByTestId('platform-outdated-agent-notice')).toHaveTextContent(
- 'delly is running an older Pulse agent (v5.1.34). Update it to v6.0.0-rc.6 for the latest agent-contributed platform detail on this host.',
+ 'delly runs an older Pulse agent (v5.1.34). Update it to v6.0.0-rc.6 for the latest agent-contributed platform detail.',
);
});
@@ -135,10 +129,10 @@ describe('PlatformOutdatedAgentNotice', () => {
));
const notice = screen.getByTestId('platform-outdated-agent-notice');
- expect(notice).toHaveTextContent('2 VMs are running an older Pulse agent.');
expect(notice).toHaveTextContent(
- 'Update them to v6.0.0-rc.6 for the latest in-guest telemetry and command support.',
+ '2 VMs run an older Pulse agent. Update them to v6.0.0-rc.6 for the latest in-guest telemetry and command support.',
);
+ fireEvent.click(screen.getByRole('button', { name: 'Which VMs?' }));
expect(notice).toHaveTextContent('Affected: app-01, db-01.');
});
});
diff --git a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx
index dd2c53ad4d..9889de0422 100644
--- a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx
+++ b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx
@@ -1,5 +1,5 @@
import { Show, createMemo, createSignal } from 'solid-js';
-import { AlertTriangle, ArrowRight } from 'lucide-solid';
+import { ArrowRight, Info } from 'lucide-solid';
import { InlineNotice } from '@/components/shared/InlineNotice';
import { presentationPolicyIsReadOnly } from '@/stores/sessionPresentationPolicy';
import type { OutdatedAgentHost } from './agentVersion';
@@ -26,18 +26,14 @@ type PlatformOutdatedAgentNoticeProps = {
// is rendered only when there is an actually-outdated resource, so the page
// stays clean in the healthy case. This is the breadcrumb that distinguishes a
// genuinely-empty detail tab from one hidden by a stale agent.
+//
+// It is maintenance, not an incident, so it is one quiet line in the info tone
+// rather than a multi-line warning above every tab: the affected names sit
+// behind a toggle and the update action stays one click away.
export function PlatformOutdatedAgentNotice(props: PlatformOutdatedAgentNoticeProps) {
const count = createMemo(() => props.hosts.length);
const names = createMemo(() => props.hosts.map((host) => host.name).join(', '));
const [showAllHosts, setShowAllHosts] = createSignal(false);
- const preview = createMemo(() => {
- const firstNames = props.hosts
- .slice(0, 3)
- .map((host) => host.name)
- .join(', ');
- const remaining = count() - 3;
- return remaining > 0 ? `${firstNames}, and ${remaining} more` : firstNames;
- });
const actionLabel = createMemo(() => props.actionLabel || 'Open Infrastructure settings');
const subjectSingular = createMemo(() => props.subjectSingular || 'host');
const subjectPlural = createMemo(() => props.subjectPlural || 'hosts');
@@ -49,14 +45,14 @@ export function PlatformOutdatedAgentNotice(props: PlatformOutdatedAgentNoticePr
if (count() === 1) {
const host = props.hosts[0];
if (copyVariant === 'latest-detail') {
- return `${host.name} is running an older Pulse agent (${host.version}). Update it${target} for the latest ${props.missingLabel} on this ${subjectSingular()}.`;
+ return `${host.name} runs an older Pulse agent (${host.version}). Update it${target} for the latest ${props.missingLabel}.`;
}
- return `${host.name} is running an older Pulse agent (${host.version}). Update it${target} to see ${props.missingLabel} for this ${subjectSingular()}.`;
+ return `${host.name} runs an older Pulse agent (${host.version}), so ${props.missingLabel} for this ${subjectSingular()} may be missing.`;
}
if (copyVariant === 'latest-detail') {
- return `${count()} ${subjectPlural()} are running an older Pulse agent. Update them${target} for the latest ${props.missingLabel}. Affected: ${preview()}.`;
+ return `${count()} ${subjectPlural()} run an older Pulse agent. Update them${target} for the latest ${props.missingLabel}.`;
}
- return `${count()} ${subjectPlural()} are running an older Pulse agent. Update them${target} to see ${props.missingLabel}. Affected: ${preview()}.`;
+ return `${count()} ${subjectPlural()} run an older Pulse agent, so ${props.missingLabel} may be missing.`;
});
return (
@@ -64,25 +60,37 @@ export function PlatformOutdatedAgentNotice(props: PlatformOutdatedAgentNoticePr
}
- actionHref={props.actionHref}
- actionLabel={actionLabel()}
- actionIcon={}
+ tone="info"
+ icon={}
>
- {message()}{' '}
- 3}>
+ {message()}
+ 1}>
+ {' '}
-
-