diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
index 143f320d5..a716b1b86 100644
--- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md
+++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
@@ -2462,6 +2462,11 @@ payload, but the browser-owned shared primitive is now the resolved
monitored-system warning banners, dashboard upsells, Patrol upgrade CTAs,
history-lock paywalls, and other public-demo commercial affordances when the
browser is rendering a public demo runtime.
+Platform stale-agent notices are also command-style upgrade affordances:
+`frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.tsx`
+must stay hidden while the resolved presentation policy marks the session
+read-only, including public demo mode, even though the same notice remains
+available for ordinary customer installs that report outdated agents.
That same shared settings-shell boundary also owns demo-mode organization
suppression. `frontend-modern/src/components/Settings/settingsNavigationModel.ts`,
`frontend-modern/src/components/Settings/settingsNavCatalog.ts`,
diff --git a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
index 3d6605024..b8953263b 100644
--- a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
+++ b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
@@ -4833,6 +4833,12 @@ describe('shared primitive guardrails', () => {
expect(source).not.toContain('rounded-lg border border-amber-300 bg-amber-50');
expect(source).not.toContain('text-amber-900 underline-offset-2');
}
+ expect(platformOutdatedAgentNoticeSource).toContain(
+ "import { presentationPolicyIsReadOnly } from '@/stores/sessionPresentationPolicy';",
+ );
+ expect(platformOutdatedAgentNoticeSource).toContain(
+ 'const visible = createMemo(() => count() > 0 && !presentationPolicyIsReadOnly());',
+ );
});
it('routes dismissible demo notices through InlineNotice banner primitives', () => {
diff --git a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
index a92bb64db..447ad0546 100644
--- a/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
+++ b/frontend-modern/src/features/platformPage/PlatformOutdatedAgentNotice.test.tsx
@@ -1,9 +1,11 @@
import { cleanup, render, screen } from '@solidjs/testing-library';
import { afterEach, describe, expect, it } from 'vitest';
+import { syncSessionPresentationPolicy } from '@/stores/sessionPresentationPolicy';
import { PlatformOutdatedAgentNotice } from './PlatformOutdatedAgentNotice';
afterEach(() => {
cleanup();
+ syncSessionPresentationPolicy(null);
});
describe('PlatformOutdatedAgentNotice', () => {
@@ -65,6 +67,31 @@ describe('PlatformOutdatedAgentNotice', () => {
);
});
+ it('hides agent upgrade commands when the session presentation policy hides upgrade prompts', () => {
+ syncSessionPresentationPolicy({
+ presentationPolicy: {
+ demoMode: true,
+ readOnly: true,
+ hideCommercial: true,
+ hideUpgrade: true,
+ },
+ });
+
+ render(() => (
+
+ ));
+
+ expect(screen.queryByTestId('platform-outdated-agent-notice')).not.toBeInTheDocument();
+ expect(screen.queryByRole('link', { name: 'Open agent upgrade commands' })).toBeNull();
+ });
+
it('can describe stale in-guest agents on VMs without host copy', () => {
render(() => (
props.actionLabel || 'Open Infrastructure settings');
const subjectSingular = createMemo(() => props.subjectSingular || 'host');
const subjectPlural = createMemo(() => props.subjectPlural || 'hosts');
+ const visible = createMemo(() => count() > 0 && !presentationPolicyIsReadOnly());
const message = createMemo(() => {
const target = props.targetVersion ? ` to ${props.targetVersion}` : '';
@@ -49,7 +51,7 @@ export function PlatformOutdatedAgentNotice(props: PlatformOutdatedAgentNoticePr
});
return (
- 0}>
+