diff --git a/docs/release-control/v6/internal/subsystems/ai-runtime.md b/docs/release-control/v6/internal/subsystems/ai-runtime.md index 9ca2e74dc..c9d24f575 100644 --- a/docs/release-control/v6/internal/subsystems/ai-runtime.md +++ b/docs/release-control/v6/internal/subsystems/ai-runtime.md @@ -1231,8 +1231,9 @@ Patrol actually succeeds or resolves them for a Patrol-owned reason. Because those findings represent Patrol blindness rather than operator-triaged infrastructure noise, the Patrol runtime must also reject manual acknowledge, snooze, dismiss, resolve, and suppress actions against synthetic `ai-service` -runtime findings. The canonical recovery path is to correct AI/provider -configuration and let Patrol re-evaluate the runtime condition on the next run. +runtime findings. The canonical recovery path is to correct Patrol provider +configuration in Assistant & Patrol settings and let Patrol re-evaluate the +runtime condition on the next run. The shared findings lifecycle must also treat a regressed issue as a new active occurrence. When a resolved finding reappears, `internal/ai/findings.go` must clear any stale acknowledgement timestamp from the prior occurrence instead of diff --git a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md index 2e7d81d31..7fa074f84 100644 --- a/docs/release-control/v6/internal/subsystems/patrol-intelligence.md +++ b/docs/release-control/v6/internal/subsystems/patrol-intelligence.md @@ -479,8 +479,8 @@ That same contract must fail closed on manual lifecycle controls too. Patrol runtime findings are Patrol-owned impairment signals, not ordinary estate findings, so the findings list must not offer generic acknowledge, snooze, dismiss, resolve, or suppress controls for them. The correct operator path is -to fix Patrol provider configuration and rerun Patrol, optionally adding context -notes, rather than hiding the runtime issue. +to fix Patrol provider configuration in Assistant & Patrol settings and rerun +Patrol, optionally adding context notes, rather than hiding the runtime issue. That same runtime-versus-infrastructure split must carry through the summary metrics strip as well. When Patrol-owned runtime issues are active, the supporting metrics must stop counting them under generic infrastructure diff --git a/internal/ai/patrol_findings.go b/internal/ai/patrol_findings.go index 9f5771f49..561e99e2a 100644 --- a/internal/ai/patrol_findings.go +++ b/internal/ai/patrol_findings.go @@ -31,7 +31,7 @@ func patrolFindingUsesSyntheticRuntimeResource(f *Finding) bool { func patrolRuntimeFindingManualActionError(action string) error { return fmt.Errorf( - "Patrol runtime findings cannot be %s manually; update AI settings and rerun Patrol", + "Patrol runtime findings cannot be %s manually; fix Patrol provider configuration in Assistant & Patrol settings and rerun Patrol", action, ) } diff --git a/internal/ai/patrol_findings_additional_test.go b/internal/ai/patrol_findings_additional_test.go index 9c77f26d1..ff6711fd4 100644 --- a/internal/ai/patrol_findings_additional_test.go +++ b/internal/ai/patrol_findings_additional_test.go @@ -111,6 +111,9 @@ func TestPatrolService_DismissFinding_RejectsPatrolRuntimeFinding(t *testing.T) if got := err.Error(); !strings.Contains(got, "cannot be dismissed manually") { t.Fatalf("unexpected error: %q", got) } + if got := err.Error(); !strings.Contains(got, "Assistant & Patrol settings") { + t.Fatalf("dismissal guidance must point to Assistant & Patrol settings: %q", got) + } stored := ps.findings.Get("runtime-1") if stored == nil { @@ -121,6 +124,32 @@ func TestPatrolService_DismissFinding_RejectsPatrolRuntimeFinding(t *testing.T) } } +func TestPatrolService_RejectManualActionForRuntimeFindingUsesProviderSettingsGuidance(t *testing.T) { + ps := NewPatrolService(nil, nil) + ps.findings.Add(&Finding{ + ID: "runtime-1", + Key: patrolRuntimeFindingKey, + Severity: FindingSeverityWarning, + Category: FindingCategoryReliability, + ResourceID: patrolRuntimeResourceID, + ResourceName: "Pulse Patrol Service", + ResourceType: "service", + Title: "Pulse Patrol: Provider not ready", + }) + + err := ps.RejectManualActionForRuntimeFinding("runtime-1", "acknowledged") + if err == nil { + t.Fatal("expected Patrol runtime finding manual action to be rejected") + } + got := err.Error() + if !strings.Contains(got, "fix Patrol provider configuration in Assistant & Patrol settings") { + t.Fatalf("manual action guidance = %q", got) + } + if strings.Contains(got, "AI settings") { + t.Fatalf("manual action guidance must not reference legacy AI settings: %q", got) + } +} + func TestPatrolFindingCreatorAdapter_IsActionable(t *testing.T) { ps := NewPatrolService(nil, nil)