From 825f230decd9953e80a0d55e3ff73e1b69bb4faa Mon Sep 17 00:00:00 2001 From: rcourtman Date: Fri, 8 May 2026 15:36:12 +0100 Subject: [PATCH] Make Patrol recommendation prompts action-aware --- .../v6/internal/subsystems/api-contracts.md | 4 +++- .../v6/internal/subsystems/frontend-primitives.md | 6 ++++-- .../v6/internal/subsystems/patrol-intelligence.md | 5 ++++- .../__tests__/patrolInvestigationContextModel.test.ts | 5 +++++ .../features/patrol/patrolInvestigationContextModel.ts | 9 +++++++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/api-contracts.md b/docs/release-control/v6/internal/subsystems/api-contracts.md index 1afe9f80c..1e72b1210 100644 --- a/docs/release-control/v6/internal/subsystems/api-contracts.md +++ b/docs/release-control/v6/internal/subsystems/api-contracts.md @@ -2028,7 +2028,9 @@ hrefs when the browser handoff already owns that route. Frontend-visible Patrol assessment briefings may render those same safe recommendation fields as separate title, reason, and route-action facts, but they must not introduce new browser-owned authority beyond the structured handoff metadata and bounded -chat context. +chat context. Browser-visible suggested prompts may follow the structured +recommendation action, such as provider-settings recovery for runtime +visibility failures, while remaining review prompts rather than API authority. Frontend handoff builders may send these fields for owned alert, incident, Patrol assessment, Patrol finding, or Patrol run-history context, but the backend must not diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index d1ebd00f7..966c791b2 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -964,8 +964,10 @@ prompt explain the same operator-facing priority. available. Assessment recommendation briefings must keep the safe recommendation title, reason, and route-owned action as separate visible drawer facts so the shared Assistant shell presents operator guidance - without parsing a compressed context sentence. Finding-level drawer opens - may also pass one bounded + without parsing a compressed context sentence. The same feature helper owns + recommendation-aware suggested prompts; shared drawer primitives must render + those prompts without replacing a provider-settings recovery path with + generic coverage wording. Finding-level drawer opens may also pass one bounded model-only finding context, one target resource reference, one safe route-owned next-step action label/href, and one `handoff_actions` reference for a live approval or proposed fix. It must not expose raw command or diff --git a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md index 3a93e1291..343ef13ef 100644 --- a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md +++ b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md @@ -279,7 +279,10 @@ Patrol-specific presentation helpers. use them for restored drawer copy without receiving the private model-only handoff context. Assessment Assistant drawer briefings must present the safe recommended step title, reason, and route-owned action as separate operator - facts instead of compressing them into an opaque context sentence. + facts instead of compressing them into an opaque context sentence, and the + suggested prompts must follow the structured recommendation action so + provider-setting/runtime-visibility failures lead with provider checks and + post-restore verification rather than generic coverage questions. When the current Patrol assessment is coverage-incomplete with no active infrastructure finding, the same handoff model must frame the briefing as a verification gap: the prompt leads with what scoped activity did and did not diff --git a/frontend-modern/src/features/patrol/__tests__/patrolInvestigationContextModel.test.ts b/frontend-modern/src/features/patrol/__tests__/patrolInvestigationContextModel.test.ts index fbdab1f2a..0644e0b03 100644 --- a/frontend-modern/src/features/patrol/__tests__/patrolInvestigationContextModel.test.ts +++ b/frontend-modern/src/features/patrol/__tests__/patrolInvestigationContextModel.test.ts @@ -471,6 +471,11 @@ describe('patrolInvestigationContextModel', () => { expect(handoff.context.briefing).toMatchObject({ actionLabel: 'Recommended: Open Patrol provider settings', actionHref: '/settings/system-ai', + suggestedPrompts: [ + 'Explain why Patrol visibility is blocked', + 'What should I check in provider settings?', + 'What should I verify after restoring Patrol?', + ], }); expect(handoff.context.briefing?.detailLines).toEqual( expect.arrayContaining([ diff --git a/frontend-modern/src/features/patrol/patrolInvestigationContextModel.ts b/frontend-modern/src/features/patrol/patrolInvestigationContextModel.ts index 1a6c333b0..4e66bb12a 100644 --- a/frontend-modern/src/features/patrol/patrolInvestigationContextModel.ts +++ b/frontend-modern/src/features/patrol/patrolInvestigationContextModel.ts @@ -1076,6 +1076,15 @@ function buildPatrolAssessmentSuggestedPrompts( normalized.correlations.length > 0 || input.investigationContext?.hasContext === true; const hasGovernedAction = normalized.findings.some(assessmentFindingHasGovernedAction); + const recommendedNextStep = normalizeAssessmentRecommendedNextStep(input.recommendedNextStep); + + if (recommendedNextStep?.actionKind === 'open_provider_settings') { + return formatPatrolSuggestedPrompts([ + 'Explain why Patrol visibility is blocked', + 'What should I check in provider settings?', + 'What should I verify after restoring Patrol?', + ]); + } if (activeFindingCount > 0) { prompts.push('Prioritize findings and safest next step');