From ac5f140802a3cf41b16dbd54a16b1ef5ba482db7 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Mon, 11 May 2026 09:21:36 +0100 Subject: [PATCH] Add conditional Verify fix button on Patrol findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourth of the seven contextual Assistant entries. Verify fix is the post-remediation confirmation step: after a fix has run, the operator asks the Assistant whether the underlying condition actually cleared, rather than trusting the fix command's exit code or the LLM's prior self-verification. - Widens PatrolAssistantFindingIntent to include 'verify_fix'. - buildPatrolAssistantFindingPrompt gains a verify_fix branch that directs the LLM to check the current evidence against the original signal that fired the finding (metrics, resource state, recent alerts, service health), then synthesize: is the condition cleared, what evidence supports that judgment, how confident, and is there residual risk to monitor for. Tool calls are allowed; state-changing commands are explicitly forbidden — verification is read-only. - FindingsPanel adds a Verify fix button after Why, gated by hasAppliedFix() which returns true for investigation outcomes fix_executed, fix_verified, fix_verification_failed, and fix_verification_unknown. For fix_queued (no fix has run yet) and fix_failed (fix didn't complete) the button is hidden because there is nothing applied to verify. - autoSendInitialPrompt extends to verify_fix; Discuss with Assistant unchanged. Test: new verify_fix-intent prompt-builder case asserts the verification dimensions (condition cleared, evidence, confidence, residual / monitor) and the read-only safety boundary, and isn't either Discuss or Investigate phrasing. --- .../src/components/AI/FindingsPanel.tsx | 53 ++++++++++++++++++- .../patrolInvestigationContextModel.test.ts | 29 ++++++++++ .../patrol/patrolInvestigationContextModel.ts | 24 ++++++++- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/frontend-modern/src/components/AI/FindingsPanel.tsx b/frontend-modern/src/components/AI/FindingsPanel.tsx index d906eca98..d84c8a388 100644 --- a/frontend-modern/src/components/AI/FindingsPanel.tsx +++ b/frontend-modern/src/components/AI/FindingsPanel.tsx @@ -518,7 +518,7 @@ export const FindingsPanel: Component = (props) => { const openFindingInAssistant = async ( finding: UnifiedFinding, - intent: 'discuss' | 'explain' | 'investigate' | 'why', + intent: 'discuss' | 'explain' | 'investigate' | 'why' | 'verify_fix', ) => { await aiIntelligenceStore.loadPendingApprovals(); const subject = getFindingSubjectPresentation(finding).label; @@ -569,7 +569,10 @@ export const FindingsPanel: Component = (props) => { aiChatStore.openWithPrompt(handoff.prompt, { ...handoff.context, autoSendInitialPrompt: - intent === 'explain' || intent === 'investigate' || intent === 'why', + intent === 'explain' || + intent === 'investigate' || + intent === 'why' || + intent === 'verify_fix', }); }; @@ -604,6 +607,34 @@ export const FindingsPanel: Component = (props) => { await openFindingInAssistant(finding, 'why'); }; + // Verify fix is the post-remediation check. After a fix has been + // executed against this finding, the operator asks the Assistant + // whether it actually worked — confirming the underlying condition + // cleared rather than trusting the fix command's exit code. Only + // meaningful when a fix has been applied (see hasAppliedFix). + const handleVerifyFixFinding = async (finding: UnifiedFinding, e: Event) => { + e.stopPropagation(); + await openFindingInAssistant(finding, 'verify_fix'); + }; + + // True when the finding has an investigation outcome indicating that + // some remediation step has run against it — anything past "fix + // queued." For these states, Verify fix is a meaningful action; for + // fix_queued (still awaiting approval) and earlier states there is + // nothing applied yet to verify, and for fix_failed the fix didn't + // complete so verification doesn't apply. + const hasAppliedFix = (finding: UnifiedFinding): boolean => { + switch (finding.investigationOutcome) { + case 'fix_executed': + case 'fix_verified': + case 'fix_verification_failed': + case 'fix_verification_unknown': + return true; + default: + return false; + } + }; + // Copy a Markdown summary of the finding to the clipboard so the operator // can paste it into a chat, ticket, or incident channel. The shape mirrors // the seven-question schema (title + impact + recommendation + trust @@ -1240,6 +1271,24 @@ export const FindingsPanel: Component = (props) => { Why + + +