diff --git a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md index f79261eaa..48d6287fd 100644 --- a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md +++ b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md @@ -192,6 +192,10 @@ operator whether Patrol recently completed a successful full patrol, only ran scoped alert-triggered checks, or ended its most recent full patrol with errors, so the page does not leave trust and coverage as implicit background knowledge. +The same hierarchy applies to investigation context. Correlations, recent +changes, and policy posture are secondary evidence for deeper investigation, so +the `Investigation context` section belongs beneath the primary findings/history +workspace rather than inside the assessment card itself. The Patrol status bar should stay factual and operational within that same hierarchy. `frontend-modern/src/components/patrol/PatrolStatusBar.tsx` is a recent-activity strip, not a second health verdict: when Patrol is active it diff --git a/frontend-modern/src/features/patrol/PatrolIntelligenceSummary.tsx b/frontend-modern/src/features/patrol/PatrolIntelligenceSummary.tsx index b3356c0ea..91fadaf11 100644 --- a/frontend-modern/src/features/patrol/PatrolIntelligenceSummary.tsx +++ b/frontend-modern/src/features/patrol/PatrolIntelligenceSummary.tsx @@ -13,9 +13,6 @@ import { } from '@/utils/patrolSummaryPresentation'; import { getPatrolRuntimePresentation } from '@/utils/patrolRuntimePresentation'; import { getSemanticTonePresentation } from '@/utils/semanticTonePresentation'; -import { ResourcePolicySummary } from '@/components/Infrastructure/ResourcePolicySummary'; -import { ResourceCorrelationSummary } from '@/components/Infrastructure/ResourceCorrelationSummary'; -import { ResourceChangeSummary } from '@/components/Infrastructure/ResourceChangeSummary'; import { formatRelativeTime } from '@/utils/format'; import type { PatrolIntelligenceState } from './usePatrolIntelligenceState'; @@ -190,66 +187,7 @@ export function PatrolIntelligenceSummary(props: { state: PatrolIntelligenceStat - - - -
-
-
-

- Investigation context -

-

- Secondary change and policy signals for deeper investigation. -

- -

- {state.investigationContextSummary()} -

-
-
- - -
- - -
- 0}> - - - -
- 0}> - - - - -
-
-
-
-
)} diff --git a/frontend-modern/src/features/patrol/PatrolIntelligenceWorkspace.tsx b/frontend-modern/src/features/patrol/PatrolIntelligenceWorkspace.tsx index 1a85f6199..2f2480013 100644 --- a/frontend-modern/src/features/patrol/PatrolIntelligenceWorkspace.tsx +++ b/frontend-modern/src/features/patrol/PatrolIntelligenceWorkspace.tsx @@ -4,6 +4,9 @@ import { ApprovalBanner, PatrolStatusBar, RunHistoryPanel } from '@/components/p import { getFindingSeverityToneClasses } from '@/utils/aiFindingPresentation'; import { formatRelativeTime } from '@/utils/format'; import { formatTriggerReason } from '@/utils/patrolFormat'; +import { ResourcePolicySummary } from '@/components/Infrastructure/ResourcePolicySummary'; +import { ResourceCorrelationSummary } from '@/components/Infrastructure/ResourceCorrelationSummary'; +import { ResourceChangeSummary } from '@/components/Infrastructure/ResourceChangeSummary'; import type { PatrolIntelligenceState } from './usePatrolIntelligenceState'; export function PatrolIntelligenceWorkspace(props: { state: PatrolIntelligenceState }) { @@ -120,6 +123,59 @@ export function PatrolIntelligenceWorkspace(props: { state: PatrolIntelligenceSt patrolStream={state.patrolStream} /> + + +
+
+
+

+ Investigation context +

+

+ Secondary change and policy signals for deeper investigation. +

+ +

{state.investigationContextSummary()}

+
+
+ + +
+ + +
+ 0}> + + + +
+ 0}> + + + + +
+
+
+
+
); } diff --git a/frontend-modern/src/pages/__tests__/AIIntelligence.test.tsx b/frontend-modern/src/pages/__tests__/AIIntelligence.test.tsx index c26b012c2..f4f486685 100644 --- a/frontend-modern/src/pages/__tests__/AIIntelligence.test.tsx +++ b/frontend-modern/src/pages/__tests__/AIIntelligence.test.tsx @@ -600,6 +600,12 @@ describe('AIIntelligence entitlement gating', () => { expect(screen.getByText('No active issues detected')).toBeInTheDocument(); }); + const findingsPanel = screen.getByTestId('findings-panel'); + const contextHeading = screen.getByText('Investigation context'); + expect( + Boolean(findingsPanel.compareDocumentPosition(contextHeading) & Node.DOCUMENT_POSITION_FOLLOWING), + ).toBe(true); + expect(screen.getByText(/Health A · 91\/100/)).toBeInTheDocument(); expect(screen.getByText('Investigation context')).toBeInTheDocument(); expect(screen.getByText('1 recent change · 4 governed resources')).toBeInTheDocument();