feat(ai): Add per-resource notes to patrol context

Knowledge store notes are now included in the patrol LLM prompt. When users
save notes about resources (e.g., 'This VM intentionally runs hot'), the patrol
AI will see these notes and avoid flagging documented behavior as issues.

Changes:
- Added knowledge store reference to PatrolService
- Added SetKnowledgeStore() method to configure the store
- Enhanced buildPatrolPrompt() to include knowledge context
- Connected knowledge store to patrol in service.go SetStateProvider()

This complements the dismissed findings context to give the LLM a complete
picture of what the user considers normal/expected behavior.
This commit is contained in:
rcourtman 2025-12-10 23:03:01 +00:00
parent a3d953172c
commit fd8cc4a32e
2 changed files with 40 additions and 3 deletions

View file

@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/ai/knowledge"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
"github.com/rs/zerolog/log"
)
@ -206,6 +207,7 @@ type PatrolService struct {
thresholdProvider ThresholdProvider
config PatrolConfig
findings *FindingsStore
knowledgeStore *knowledge.Store // For per-resource notes in patrol context
// Cached thresholds (recalculated when thresholdProvider changes)
thresholds PatrolThresholds
@ -320,6 +322,13 @@ func (p *PatrolService) SetRunHistoryPersistence(persistence PatrolHistoryPersis
return nil
}
// SetKnowledgeStore sets the knowledge store for including per-resource notes in patrol context
func (p *PatrolService) SetKnowledgeStore(store *knowledge.Store) {
p.mu.Lock()
defer p.mu.Unlock()
p.knowledgeStore = store
}
// GetConfig returns the current patrol configuration
func (p *PatrolService) GetConfig() PatrolConfig {
p.mu.RLock()
@ -1632,6 +1641,15 @@ func (p *PatrolService) buildPatrolPrompt(summary string, deep bool) string {
// Get user feedback context (dismissed/snoozed findings)
feedbackContext := p.findings.GetDismissedForContext()
// Get resource notes from knowledge store (per-resource user notes)
var knowledgeContext string
p.mu.RLock()
knowledgeStore := p.knowledgeStore
p.mu.RUnlock()
if knowledgeStore != nil {
knowledgeContext = knowledgeStore.FormatAllForContext()
}
basePrompt := fmt.Sprintf(`Please perform a comprehensive analysis of the following infrastructure and identify any issues, potential problems, or optimization opportunities.
%s
@ -1645,16 +1663,31 @@ Analyze the above and report any findings using the structured format. Focus on:
If everything looks healthy, say so briefly.`, summary)
// If there's user feedback, append instructions
var contextAdditions strings.Builder
// Append knowledge context (user notes about resources)
if knowledgeContext != "" {
contextAdditions.WriteString("\n\n")
contextAdditions.WriteString(knowledgeContext)
contextAdditions.WriteString("\nIMPORTANT: Consider the user's saved notes above when analyzing. If a user has noted that a resource behaves a certain way (e.g., 'runs hot for transcoding'), do not flag it as an issue.\n")
}
// Append user feedback context (dismissed/snoozed findings)
if feedbackContext != "" {
return basePrompt + "\n\n" + feedbackContext + `
contextAdditions.WriteString("\n\n")
contextAdditions.WriteString(feedbackContext)
contextAdditions.WriteString(`
IMPORTANT: Respect the user's feedback above. Do NOT re-raise findings that are:
- Permanently suppressed - the user has explicitly said to never mention these again
- Dismissed as "not_an_issue" or "expected_behavior" - the user knows about these
- Currently snoozed - only re-raise if the severity has significantly worsened
Only report NEW issues or issues where the severity has clearly escalated.`
Only report NEW issues or issues where the severity has clearly escalated.`)
}
if contextAdditions.Len() > 0 {
return basePrompt + contextAdditions.String()
}
return basePrompt

View file

@ -75,6 +75,10 @@ func (s *Service) SetStateProvider(sp StateProvider) {
// Initialize patrol service if not already done
if s.patrolService == nil && sp != nil {
s.patrolService = NewPatrolService(s, sp)
// Connect knowledge store to patrol for per-resource notes in context
if s.knowledgeStore != nil {
s.patrolService.SetKnowledgeStore(s.knowledgeStore)
}
}
// Initialize alert-triggered analyzer if not already done