mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-14 16:40:30 +00:00
Differentiate Patrol no-findings from all-clear
Patrol findings empty states now interpret degraded assessment context instead of repeating the summary prediction verbatim.
This commit is contained in:
parent
38fc165922
commit
2dd90da65e
4 changed files with 52 additions and 4 deletions
|
|
@ -120,6 +120,12 @@ overall-health summary is degraded or not fully verified. The green healthy
|
|||
empty state belongs only to an actually healthy Patrol summary, while degraded
|
||||
coverage or paused-runtime states must surface the governing warning/error copy
|
||||
through `frontend-modern/src/utils/patrolEmptyStatePresentation.ts`.
|
||||
That degraded empty-state copy must also interpret the finding state rather
|
||||
than simply replaying the primary assessment sentence verbatim: when coverage
|
||||
is incomplete, the findings panel should tell the operator that Patrol has not
|
||||
surfaced active findings but that this is not a full all-clear, so the page
|
||||
does not duplicate the summary prediction as if it were a second independent
|
||||
status surface.
|
||||
The Patrol summary surface must follow that same hierarchy. The primary summary
|
||||
headline in `frontend-modern/src/features/patrol/PatrolIntelligenceSummary.tsx`
|
||||
should state Patrol's current assessment first, such as verified healthy,
|
||||
|
|
|
|||
|
|
@ -818,6 +818,11 @@ describe('AIIntelligence entitlement gating', () => {
|
|||
|
||||
expect(screen.queryByText('No issues found')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Partial verification')).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.getAllByText(
|
||||
'Patrol coverage is incomplete: recent activity was limited to scoped runs and ended with errors, so overall health is not fully verified.',
|
||||
),
|
||||
).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('treats a selected zero-finding run as an empty snapshot and uses effective scope ids', async () => {
|
||||
|
|
|
|||
|
|
@ -59,11 +59,38 @@ describe('patrolEmptyStatePresentation', () => {
|
|||
}),
|
||||
).toEqual({
|
||||
title: 'No active findings',
|
||||
body: 'Patrol coverage is incomplete: recent activity was limited to scoped runs and ended with errors, so overall health is not fully verified.',
|
||||
body: 'Patrol has not surfaced active findings, but coverage is incomplete, so this is not a full all-clear.',
|
||||
tone: 'warning',
|
||||
});
|
||||
});
|
||||
|
||||
it('uses an attention-focused empty state when patrol health is degraded for non-coverage reasons', () => {
|
||||
expect(
|
||||
getPatrolFindingsEmptyState({
|
||||
filter: 'active',
|
||||
overallHealth: {
|
||||
score: 45,
|
||||
grade: 'D',
|
||||
trend: 'declining',
|
||||
factors: [
|
||||
{
|
||||
name: 'Critical unresolved risk',
|
||||
impact: -0.55,
|
||||
description: 'Recent Patrol evidence indicates unresolved infrastructure risk.',
|
||||
category: 'findings',
|
||||
},
|
||||
],
|
||||
prediction: 'Critical infrastructure risk still requires attention.',
|
||||
},
|
||||
runtimeState: 'active',
|
||||
}),
|
||||
).toEqual({
|
||||
title: 'No active findings',
|
||||
body: 'Patrol has not surfaced active findings, but the overall Patrol assessment still needs attention.',
|
||||
tone: 'error',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the patrol runtime explanation when the runtime is blocked', () => {
|
||||
expect(
|
||||
getPatrolFindingsEmptyState({
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ export interface PatrolFindingsEmptyStateCopy {
|
|||
}
|
||||
|
||||
const HEALTHY_PATROL_EMPTY_STATE_BODY = 'Your infrastructure looks healthy!';
|
||||
const DEGRADED_COVERAGE_EMPTY_STATE_BODY =
|
||||
'Patrol has not surfaced active findings, but coverage is incomplete, so this is not a full all-clear.';
|
||||
const DEGRADED_HEALTH_EMPTY_STATE_BODY =
|
||||
'Patrol has not surfaced active findings, but the overall Patrol assessment still needs attention.';
|
||||
|
||||
function getHealthDegradedTone(overallHealth: IntelligenceHealthScore): SemanticTone {
|
||||
return overallHealth.grade === 'D' || overallHealth.grade === 'F' ? 'error' : 'warning';
|
||||
|
|
@ -77,6 +81,14 @@ function shouldSuppressHealthyEmptyState(overallHealth: IntelligenceHealthScore
|
|||
return overallHealth.grade !== 'A';
|
||||
}
|
||||
|
||||
function getDegradedPatrolEmptyStateBody(overallHealth: IntelligenceHealthScore): string {
|
||||
if (overallHealth.factors.some((factor) => factor.category === 'coverage')) {
|
||||
return DEGRADED_COVERAGE_EMPTY_STATE_BODY;
|
||||
}
|
||||
|
||||
return DEGRADED_HEALTH_EMPTY_STATE_BODY;
|
||||
}
|
||||
|
||||
export function getPatrolFindingsEmptyState(args: {
|
||||
filter: FindingsFilter;
|
||||
overallHealth?: IntelligenceHealthScore;
|
||||
|
|
@ -106,9 +118,7 @@ export function getPatrolFindingsEmptyState(args: {
|
|||
if (shouldSuppressHealthyEmptyState(args.overallHealth)) {
|
||||
return {
|
||||
title: 'No active findings',
|
||||
body:
|
||||
args.overallHealth?.prediction?.trim() ||
|
||||
'Patrol has not surfaced active findings, but overall infrastructure health is not fully verified.',
|
||||
body: getDegradedPatrolEmptyStateBody(args.overallHealth!),
|
||||
tone: getHealthDegradedTone(args.overallHealth!),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue