Hide empty investigation context

This commit is contained in:
rcourtman
2026-03-23 10:10:20 +00:00
parent 8204f735d2
commit b85c4473e8
3 changed files with 42 additions and 6 deletions
@@ -213,6 +213,11 @@ The drawer investigation summary line also follows that boundary now: default
`Cloud Summary` routing is not repeated in the collapsed summary text, while
non-default routing still appears when it materially changes how the operator
should read the resource.
The drawer now also suppresses the investigation-context section entirely when
Patrol returns only generic baseline health with no notes, changes,
correlations, dependencies, or other non-default governance signal. The
canonical resource surface should not advertise AI context unless there is
actual investigative value to show.
The shared routing policy itself now stays intentionally minimal: it carries
only the routing scope and the redaction hints derived from canonical
sensitivity, and the cloud-summary decision is derived from that scope
@@ -354,6 +354,22 @@ describe('ResourceDetailDrawer change history section', () => {
});
it('keeps default internal cloud-summary posture out of the investigation context drawer block', async () => {
aiIntelligenceMock.getResourceIntelligence.mockResolvedValueOnce({
resource_id: 'agent-default-policy',
health: {
score: 100,
grade: 'A',
trend: 'stable',
factors: [],
prediction: '',
},
dependencies: [],
dependents: [],
correlations: [],
recent_changes: [],
note_count: 0,
});
const resource = baseResource({
id: 'agent-default-policy',
name: 'default-policy-host',
@@ -369,10 +385,8 @@ describe('ResourceDetailDrawer change history section', () => {
render(() => <ResourceDetailDrawer resource={resource} />);
await screen.findByText('Investigation context');
expect(screen.queryByText('Routing Cloud Summary')).toBeNull();
fireEvent.click(screen.getByRole('button', { name: 'Show context' }));
await screen.findByText('Current state');
expect(screen.queryByText('Investigation context')).toBeNull();
expect(screen.queryByText('Data Governance')).toBeNull();
expect(screen.queryByText('AI-Safe Summary')).toBeNull();
expect(screen.queryByText('Routing Cloud Summary')).toBeNull();
@@ -181,6 +181,22 @@ export const useResourceDetailDrawerDerivedState = (
const resourceDependencies = createMemo(() => resourceIntelligence()?.dependencies ?? []);
const resourceDependents = createMemo(() => resourceIntelligence()?.dependents ?? []);
const resourceCorrelations = createMemo(() => resourceIntelligence()?.correlations ?? []);
const hasMeaningfulResourceIntelligence = createMemo(() => {
const intel = resourceIntelligence();
if (!intel) return false;
return (
(intel.health.score ?? 100) < 100 ||
intel.health.trend !== 'stable' ||
(intel.health.prediction?.trim() ?? '') !== '' ||
(intel.health.factors?.length ?? 0) > 0 ||
(intel.note_count ?? 0) > 0 ||
(intel.recent_changes?.length ?? 0) > 0 ||
resourceDependencies().length > 0 ||
resourceDependents().length > 0 ||
resourceCorrelations().length > 0
);
});
const hasCorrelationContext = createMemo(
() =>
resourceDependencies().length > 0 ||
@@ -188,13 +204,13 @@ export const useResourceDetailDrawerDerivedState = (
resourceCorrelations().length > 0,
);
const hasInvestigationContext = createMemo(
() => Boolean(resourceIntelligence()) || hasGovernanceData(),
() => hasMeaningfulResourceIntelligence() || hasGovernanceData(),
);
const investigationContextSummary = createMemo(() => {
const intel = resourceIntelligence();
const summary: string[] = [];
if (intel) {
if (intel && hasMeaningfulResourceIntelligence()) {
summary.push(`AI health ${intel.health.grade} · ${Math.round(intel.health.score)}/100`);
}
if (resourceCorrelations().length > 0) {
@@ -555,6 +571,7 @@ export const useResourceDetailDrawerDerivedState = (
resourceDependents,
resourceCorrelations,
hasCorrelationContext,
hasMeaningfulResourceIntelligence,
hasInvestigationContext,
investigationContextSummary,
pbsData,