package model import ( "encoding/json" "time" ) type LinkedItem struct { ItemType string `json:"item_type"` ID int64 `json:"id"` Name string `json:"name,omitempty"` } type Ticket struct { ID int64 `json:"id"` Name string `json:"name"` Content string `json:"content"` DateCreation string `json:"date_creation,omitempty"` DateMod string `json:"date_mod"` StatusID int64 `json:"status_id"` CategoryID int64 `json:"category_id"` Priority int64 `json:"priority,omitempty"` Impact int64 `json:"impact,omitempty"` Urgency int64 `json:"urgency,omitempty"` EntityID int64 `json:"entity_id,omitempty"` LocationID int64 `json:"location_id,omitempty"` TimeToResolve string `json:"time_to_resolve,omitempty"` RequesterIDs []int64 `json:"requester_ids,omitempty"` AssignedGroups []int64 `json:"assigned_group_ids,omitempty"` AssignedUsers []int64 `json:"assigned_user_ids,omitempty"` Items []LinkedItem `json:"items,omitempty"` } type Followup struct { ID int64 `json:"id"` Content string `json:"content"` IsPrivate bool `json:"is_private"` UserID int64 `json:"user_id"` Date string `json:"date"` } type Category struct { ID int64 `json:"id"` Name string `json:"name"` CompleteName string `json:"completename"` // KnowbaseCategoryID is the GLPI knowledge-base category associated with // this ITIL category, when the installed GLPI exposes that relation. KnowbaseCategoryID int64 `json:"knowbase_category_id,omitempty"` Hints []string `json:"hints,omitempty"` Examples []string `json:"confirmed_examples,omitempty"` } type LearningExample struct { ID string `json:"id"` RunID string `json:"run_id,omitempty"` TicketID int64 `json:"ticket_id,omitempty"` Subject string `json:"subject"` Text string `json:"text"` CategoryID int64 `json:"category_id"` CategoryName string `json:"category_name"` AIRecommendedCategoryID int64 `json:"ai_recommended_category_id,omitempty"` AIConfidence float64 `json:"ai_confidence,omitempty"` Correction bool `json:"correction"` CreatedAt time.Time `json:"created_at"` Source string `json:"source"` } type KnowledgeDoc struct { ID string `json:"id"` Title string `json:"title"` Text string `json:"text"` Answer string `json:"answer"` // AnswerHTML contains trusted rich text from a synchronized GLPI KB item. // It is never sent to the LLM or used for embeddings. AnswerHTML string `json:"answer_html,omitempty"` AutoReply bool `json:"auto_reply"` // AutoReplyDecision explains why a synchronized source document is or is // not eligible for automatic replies. Local JSON documents may leave this // empty because their explicit auto_reply flag is already authoritative. AutoReplyDecision string `json:"auto_reply_decision,omitempty"` AutoReplyDetail string `json:"auto_reply_detail,omitempty"` MinScore float64 `json:"min_score"` Categories []int64 `json:"categories"` ExternalCategories []string `json:"external_categories,omitempty"` UnmappedExternalCategories []string `json:"unmapped_external_categories,omitempty"` Keywords []string `json:"keywords"` Source string `json:"source"` SourceURI string `json:"source_uri,omitempty"` SourceCategoryIDs []int64 `json:"source_category_ids,omitempty"` SourceModifiedAt string `json:"source_modified_at,omitempty"` Language string `json:"language"` CommunicationStyle string `json:"communication_style"` } // GLPIKnowledgeItem is the normalized read-only representation returned by // the GLPI connector before it is converted into a KnowledgeDoc. type GLPIKnowledgeItem struct { ID int64 `json:"id"` Title string `json:"title"` Content string `json:"content"` CategoryIDs []int64 `json:"category_ids,omitempty"` Language string `json:"language,omitempty"` ModifiedAt string `json:"modified_at,omitempty"` } type KnowledgeHit struct { Doc KnowledgeDoc `json:"doc"` Score float64 `json:"score"` SemanticScore float64 `json:"semantic_score,omitempty"` TitleScore float64 `json:"title_score,omitempty"` LexicalScore float64 `json:"lexical_score,omitempty"` KeywordScore float64 `json:"keyword_score,omitempty"` CategoryScore float64 `json:"category_score,omitempty"` BestChunkExcerpt string `json:"best_chunk_excerpt,omitempty"` BestQueryExcerpt string `json:"best_query_excerpt,omitempty"` QueryChunkCount int `json:"query_chunk_count,omitempty"` DocumentChunkCount int `json:"document_chunk_count,omitempty"` } // ChangeContext is a normalized, read-only view of a GLPI Change. Only fields // useful for ticket triage are passed to the model. type ChangeContext struct { ID int64 `json:"id"` Name string `json:"name"` Content string `json:"content,omitempty"` StatusID int64 `json:"status_id,omitempty"` CategoryID int64 `json:"category_id,omitempty"` PlannedBegin string `json:"planned_begin,omitempty"` PlannedEnd string `json:"planned_end,omitempty"` DateMod string `json:"date_mod,omitempty"` Relevance float64 `json:"relevance"` Source string `json:"source"` } type MajorIncidentContext struct { ID int64 `json:"id"` Name string `json:"name"` Content string `json:"content,omitempty"` StatusID int64 `json:"status_id,omitempty"` CategoryID int64 `json:"category_id,omitempty"` Priority int64 `json:"priority,omitempty"` Impact int64 `json:"impact,omitempty"` Urgency int64 `json:"urgency,omitempty"` DateMod string `json:"date_mod,omitempty"` Relevance float64 `json:"relevance"` Source string `json:"source"` } type ServiceIssueCandidate struct { ID string `json:"id"` Issue ServiceIssueContext `json:"issue"` } type StatusDecision struct { Matched bool `json:"matched"` CandidateID string `json:"candidate_id"` Confidence float64 `json:"confidence"` Reason string `json:"reason"` } type ServiceIssueContext struct { Source string `json:"source"` StatusPage string `json:"status_page"` Kind string `json:"kind"` // monitor | pinned_incident | maintenance MonitorID int64 `json:"monitor_id,omitempty"` MonitorName string `json:"monitor_name,omitempty"` Status string `json:"status"` Message string `json:"message,omitempty"` LastHeartbeat string `json:"last_heartbeat,omitempty"` Uptime24h float64 `json:"uptime_24h,omitempty"` IncidentTitle string `json:"incident_title,omitempty"` IncidentContent string `json:"incident_content,omitempty"` Relevance float64 `json:"relevance"` } type UserDeviceContext struct { UserID int64 `json:"user_id,omitempty"` ItemType string `json:"item_type"` ID int64 `json:"id"` Name string `json:"name,omitempty"` Serial string `json:"serial,omitempty"` InventoryNumber string `json:"inventory_number,omitempty"` Status string `json:"status,omitempty"` Location string `json:"location,omitempty"` LastInventoryDate string `json:"last_inventory_date,omitempty"` Source string `json:"source"` } type ContextSnapshot struct { FetchedAt time.Time `json:"fetched_at"` Changes []ChangeContext `json:"changes,omitempty"` MajorIncidents []MajorIncidentContext `json:"major_incidents,omitempty"` ServiceIssues []ServiceIssueContext `json:"service_issues,omitempty"` UserDevices []UserDeviceContext `json:"user_devices,omitempty"` Warnings []string `json:"warnings,omitempty"` Incomplete bool `json:"incomplete"` } func (c ContextSnapshot) HasRelevantIncident(minScore float64) bool { for _, incident := range c.MajorIncidents { if incident.Relevance >= minScore { return true } } for _, issue := range c.ServiceIssues { if issue.Relevance >= minScore && (issue.Status == "down" || issue.Status == "pending" || issue.Kind == "pinned_incident") { return true } } return false } type Decision struct { Category struct { ID int64 `json:"id"` Confidence float64 `json:"confidence"` } `json:"category"` Reply struct { Allowed bool `json:"allowed"` Confidence float64 `json:"confidence"` KnowledgeID string `json:"knowledge_id"` } `json:"reply"` Reason string `json:"reason"` } // RuleCheck is a machine-readable explanation of one deterministic decision gate. // Status is one of: pass, fail, warn, info, na. type RuleCheck struct { Code string `json:"code"` Group string `json:"group,omitempty"` Label string `json:"label"` Status string `json:"status"` Blocking bool `json:"blocking,omitempty"` Actual string `json:"actual,omitempty"` Expected string `json:"expected,omitempty"` Detail string `json:"detail,omitempty"` } // KnowledgeDiagnostic explains why one knowledge article was or was not // considered for a specific ticket run. The score is recalculated against the // current knowledge index; CurrentTicketChanged tells the UI when the ticket has // changed since the historical run. type KnowledgeDiagnostic struct { RunID string `json:"run_id"` Purpose string `json:"purpose,omitempty"` TicketID int64 `json:"ticket_id"` KnowledgeID string `json:"knowledge_id"` Title string `json:"title"` Source string `json:"source"` CurrentTicketChanged bool `json:"current_ticket_changed"` RetrievalRank int `json:"retrieval_rank"` RetrievalScore float64 `json:"retrieval_score"` SemanticScore float64 `json:"semantic_score,omitempty"` TitleScore float64 `json:"title_score,omitempty"` LexicalScore float64 `json:"lexical_score,omitempty"` KeywordScore float64 `json:"keyword_score,omitempty"` CategoryScore float64 `json:"category_score,omitempty"` CandidateCutoff float64 `json:"candidate_cutoff,omitempty"` SentToAI bool `json:"sent_to_ai"` SelectionReason string `json:"selection_reason"` AISelected bool `json:"ai_selected"` EvidenceScore float64 `json:"evidence_score,omitempty"` RequiredScore float64 `json:"required_score,omitempty"` BestChunkExcerpt string `json:"best_chunk_excerpt,omitempty"` BestQueryExcerpt string `json:"best_query_excerpt,omitempty"` ExternalCategories []string `json:"external_categories,omitempty"` UnmappedCategories []string `json:"unmapped_categories,omitempty"` Checks []RuleCheck `json:"checks"` Document KnowledgeDoc `json:"document"` } type PolicyResult struct { ChangeCategory bool `json:"change_category"` CategoryID int64 `json:"category_id"` CategoryRecommendationID int64 `json:"category_recommendation_id"` CategoryRecommendationName string `json:"category_recommendation_name,omitempty"` CategoryConfidence float64 `json:"category_confidence"` CategoryThreshold float64 `json:"category_threshold"` CategoryDecision string `json:"category_decision"` Reply bool `json:"reply"` ReplyText string `json:"reply_text,omitempty"` ReplyIsHTML bool `json:"reply_is_html,omitempty"` KnowledgeID string `json:"knowledge_id,omitempty"` ReplyRecommendation bool `json:"reply_recommendation"` ReplyConfidence float64 `json:"reply_confidence"` ReplyThreshold float64 `json:"reply_threshold"` ReplyKnowledgeID string `json:"reply_knowledge_id,omitempty"` ReplyDecision string `json:"reply_decision"` KnowledgeThreshold float64 `json:"knowledge_threshold,omitempty"` KnowledgeRetrievalScore float64 `json:"knowledge_retrieval_score,omitempty"` KnowledgeEvidenceScore float64 `json:"knowledge_evidence_score,omitempty"` KnowledgeRetrievalFloor float64 `json:"knowledge_retrieval_floor,omitempty"` KnowledgeCategoryAligned bool `json:"knowledge_category_aligned,omitempty"` AIReason string `json:"ai_reason,omitempty"` CategoryChecks []RuleCheck `json:"category_checks,omitempty"` ReplyChecks []RuleCheck `json:"reply_checks,omitempty"` } // KnowledgeCandidateAudit captures the top retrieval candidates used for a run. // It intentionally stores only normalized, non-secret diagnostic information. type KnowledgeCandidateAudit struct { ID string `json:"id"` Title string `json:"title"` Source string `json:"source"` Score float64 `json:"score"` SemanticScore float64 `json:"semantic_score,omitempty"` TitleScore float64 `json:"title_score,omitempty"` LexicalScore float64 `json:"lexical_score,omitempty"` KeywordScore float64 `json:"keyword_score,omitempty"` CategoryScore float64 `json:"category_score,omitempty"` RequiredScore float64 `json:"required_score,omitempty"` AutoReply bool `json:"auto_reply"` AutoReplyDecision string `json:"auto_reply_decision,omitempty"` AutoReplyDetail string `json:"auto_reply_detail,omitempty"` BestChunkExcerpt string `json:"best_chunk_excerpt,omitempty"` BestQueryExcerpt string `json:"best_query_excerpt,omitempty"` QueryChunkCount int `json:"query_chunk_count,omitempty"` DocumentChunkCount int `json:"document_chunk_count,omitempty"` SentToAI bool `json:"sent_to_ai,omitempty"` RetrievalRank int `json:"retrieval_rank,omitempty"` SelectionReason string `json:"selection_reason,omitempty"` } // ContextAuditItem is a compact snapshot of context that influenced a run. type StatusCandidateAudit struct { ID string `json:"id"` Name string `json:"name"` Kind string `json:"kind"` Status string `json:"status"` Relevance float64 `json:"relevance"` AISelected bool `json:"ai_selected,omitempty"` AIConfidence float64 `json:"ai_confidence,omitempty"` FinalScore float64 `json:"final_score,omitempty"` Decision string `json:"decision,omitempty"` } type ContextAuditItem struct { Kind string `json:"kind"` ID int64 `json:"id,omitempty"` Name string `json:"name"` Status string `json:"status,omitempty"` Relevance float64 `json:"relevance,omitempty"` Detail string `json:"detail,omitempty"` } // AnalysisRun is one independently auditable AI or deterministic analysis stage. // OllamaRequestAttempt captures one concrete HTTP attempt against an Ollama node. // It is attached to an AnalysisRun so routing and failover remain auditable. type OllamaRequestAttempt struct { Attempt int `json:"attempt"` Stage string `json:"stage,omitempty"` Path string `json:"path,omitempty"` NodeName string `json:"node_name"` NodeURL string `json:"node_url"` ModelDigest string `json:"model_digest,omitempty"` StartedAt time.Time `json:"started_at"` DurationMS int64 `json:"duration_ms"` InflightAtStart int64 `json:"inflight_at_start,omitempty"` HTTPStatus int `json:"http_status,omitempty"` Outcome string `json:"outcome"` Retryable bool `json:"retryable,omitempty"` Error string `json:"error,omitempty"` TotalDurationNS int64 `json:"total_duration_ns,omitempty"` LoadDurationNS int64 `json:"load_duration_ns,omitempty"` PromptEvalCount int64 `json:"prompt_eval_count,omitempty"` PromptEvalDuration int64 `json:"prompt_eval_duration_ns,omitempty"` EvalCount int64 `json:"eval_count,omitempty"` EvalDuration int64 `json:"eval_duration_ns,omitempty"` } // OllamaProviderTrace summarizes the routing of one logical analysis. type OllamaProviderTrace struct { Provider string `json:"provider,omitempty"` RoutingMode string `json:"routing_mode,omitempty"` SelectedNode string `json:"selected_node,omitempty"` SelectedURL string `json:"selected_url,omitempty"` FailoverUsed bool `json:"failover_used,omitempty"` AttemptCount int `json:"attempt_count,omitempty"` Attempts []OllamaRequestAttempt `json:"attempts,omitempty"` } // OllamaNodeStatus is the read-only operational state exposed in the dashboard. type OllamaNodeStatus struct { Name string `json:"name"` URL string `json:"url"` Weight int `json:"weight"` Healthy bool `json:"healthy"` Compatible bool `json:"compatible"` Available bool `json:"available"` InFlight int64 `json:"inflight"` MaxInFlight int `json:"max_inflight"` ChatModelDigest string `json:"chat_model_digest,omitempty"` EmbeddingModelDigest string `json:"embedding_model_digest,omitempty"` LastCheck time.Time `json:"last_check,omitempty"` LastSuccess time.Time `json:"last_success,omitempty"` CooldownUntil time.Time `json:"cooldown_until,omitempty"` ConsecutiveFailures int `json:"consecutive_failures,omitempty"` LastError string `json:"last_error,omitempty"` Requests uint64 `json:"requests"` Failures uint64 `json:"failures"` AverageDurationMS float64 `json:"average_duration_ms,omitempty"` LastRequestDurationMS int64 `json:"last_request_duration_ms,omitempty"` } // Decision and InputSnapshot contain the exact structured values used at execution // time, so later diagnostics do not depend on the current ticket or configuration. type AnalysisRun struct { AnalysisID string `json:"analysis_id"` ParentRunID string `json:"parent_run_id"` TicketID int64 `json:"ticket_id"` AnalysisType string `json:"analysis_type"` Trigger string `json:"trigger"` SourceVersion string `json:"source_version"` Model string `json:"model,omitempty"` PromptVersion string `json:"prompt_version,omitempty"` InputHash string `json:"input_hash,omitempty"` InputSnapshot json.RawMessage `json:"input_snapshot,omitempty"` StartedAt time.Time `json:"started_at"` FinishedAt time.Time `json:"finished_at"` DurationMS int64 `json:"duration_ms"` Outcome string `json:"outcome"` Error string `json:"error,omitempty"` Decision json.RawMessage `json:"decision,omitempty"` ReasonCodes []string `json:"reason_codes,omitempty"` Explanation string `json:"explanation,omitempty"` Confidence float64 `json:"confidence,omitempty"` Checks []RuleCheck `json:"checks,omitempty"` Action ActionAudit `json:"action,omitempty"` Provider OllamaProviderTrace `json:"provider,omitempty"` } type ActionStepAudit struct { Step string `json:"step,omitempty"` Target string `json:"target,omitempty"` Proposed bool `json:"proposed,omitempty"` Executed bool `json:"executed,omitempty"` DryRun bool `json:"dry_run,omitempty"` Before string `json:"before,omitempty"` After string `json:"after,omitempty"` Result string `json:"result,omitempty"` Error string `json:"error,omitempty"` } type ActionAudit struct { Type string `json:"type,omitempty"` Target string `json:"target,omitempty"` Proposed bool `json:"proposed,omitempty"` Executed bool `json:"executed,omitempty"` DryRun bool `json:"dry_run,omitempty"` Before string `json:"before,omitempty"` After string `json:"after,omitempty"` Result string `json:"result,omitempty"` Error string `json:"error,omitempty"` Steps []ActionStepAudit `json:"steps,omitempty"` } type PriorityDecision struct { RecommendedPriority int64 `json:"recommended_priority"` RecommendedImpact int64 `json:"recommended_impact"` RecommendedUrgency int64 `json:"recommended_urgency"` AffectedScope string `json:"affected_scope"` TimeCriticality string `json:"time_criticality"` ReasonCodes []string `json:"reason_codes"` Confidence float64 `json:"confidence"` Reason string `json:"reason"` } type PriorityResult struct { Accepted bool `json:"accepted"` ChangePriority bool `json:"change_priority"` PriorityBefore int64 `json:"priority_before"` PriorityAfter int64 `json:"priority_after"` RecommendedPriority int64 `json:"recommended_priority"` RecommendedImpact int64 `json:"recommended_impact,omitempty"` RecommendedUrgency int64 `json:"recommended_urgency,omitempty"` AffectedScope string `json:"affected_scope,omitempty"` TimeCriticality string `json:"time_criticality,omitempty"` Confidence float64 `json:"confidence"` Decision string `json:"decision"` ReasonCodes []string `json:"reason_codes,omitempty"` Checks []RuleCheck `json:"checks,omitempty"` } type EscalationDecision struct { Escalate bool `json:"escalate"` Level int `json:"level"` RecommendedAction string `json:"recommended_action,omitempty"` // legacy compatibility RecommendedActions []string `json:"recommended_actions,omitempty"` ReasonCodes []string `json:"reason_codes"` Confidence float64 `json:"confidence"` Reason string `json:"reason"` } type EscalationEvidence struct { TicketAge string `json:"ticket_age"` NoHumanResponse bool `json:"no_human_response"` HumanActivityIncomplete bool `json:"human_activity_incomplete,omitempty"` LastHumanActivity string `json:"last_human_activity,omitempty"` InactiveFor string `json:"inactive_for,omitempty"` InactivityRequired string `json:"inactivity_required,omitempty"` Unassigned bool `json:"unassigned"` SLADeadline string `json:"sla_deadline,omitempty"` SLABreached bool `json:"sla_breached"` SLAAtRisk bool `json:"sla_at_risk"` SLARemaining string `json:"sla_remaining,omitempty"` MajorIncidentID int64 `json:"major_incident_id,omitempty"` MajorIncidentName string `json:"major_incident_name,omitempty"` MajorIncidentScore float64 `json:"major_incident_score,omitempty"` } type EscalationConstraints struct { AllowedActions []string `json:"allowed_actions"` AllowedReasonCodes []string `json:"allowed_reason_codes"` MaxLevel int `json:"max_level"` MinimumAge string `json:"minimum_age"` ServiceOwnerMinLevel int `json:"service_owner_min_level"` ManagerReviewMinLevel int `json:"manager_review_min_level"` MajorIncidentMinRelevance float64 `json:"major_incident_min_relevance"` ConfiguredTargets []string `json:"configured_targets,omitempty"` } type EscalationActionResult struct { Action string `json:"action"` Target string `json:"target,omitempty"` Accepted bool `json:"accepted"` Decision string `json:"decision"` Checks []RuleCheck `json:"checks,omitempty"` IdempotencyKey string `json:"idempotency_key,omitempty"` } type EscalationResult struct { Accepted bool `json:"accepted"` Level int `json:"level"` Action string `json:"action,omitempty"` // first accepted action for compatibility Actions []EscalationActionResult `json:"actions,omitempty"` Decision string `json:"decision"` ReasonCodes []string `json:"reason_codes,omitempty"` Checks []RuleCheck `json:"checks,omitempty"` IdempotencyKey string `json:"idempotency_key,omitempty"` // first accepted action for compatibility } type RunRecord struct { RunID string `json:"run_id"` TicketID int64 `json:"ticket_id"` TicketName string `json:"ticket_name"` SourceVersion string `json:"source_version"` Trigger string `json:"trigger,omitempty"` CausedByRunID string `json:"caused_by_run_id,omitempty"` StartedAt time.Time `json:"started_at"` FinishedAt time.Time `json:"finished_at"` Outcome string `json:"outcome"` Reason string `json:"reason"` AIReason string `json:"ai_reason,omitempty"` CategoryAIReason string `json:"category_ai_reason,omitempty"` ReplyAIReason string `json:"reply_ai_reason,omitempty"` CategoryAnalysisExecuted bool `json:"category_analysis_executed,omitempty"` ReplyAnalysisExecuted bool `json:"reply_analysis_executed,omitempty"` ReplyAnalysisSkipReason string `json:"reply_analysis_skip_reason,omitempty"` CategoryAnalysisDurationMS int64 `json:"category_analysis_duration_ms,omitempty"` ReplyAnalysisDurationMS int64 `json:"reply_analysis_duration_ms,omitempty"` PriorityAnalysisExecuted bool `json:"priority_analysis_executed,omitempty"` PriorityAnalysisDurationMS int64 `json:"priority_analysis_duration_ms,omitempty"` PriorityAIReason string `json:"priority_ai_reason,omitempty"` PriorityBefore int64 `json:"priority_before,omitempty"` AIRecommendedPriority int64 `json:"ai_recommended_priority,omitempty"` AIRecommendedImpact int64 `json:"ai_recommended_impact,omitempty"` AIRecommendedUrgency int64 `json:"ai_recommended_urgency,omitempty"` PriorityAffectedScope string `json:"priority_affected_scope,omitempty"` PriorityTimeCriticality string `json:"priority_time_criticality,omitempty"` AIPriorityConfidence float64 `json:"ai_priority_confidence,omitempty"` PriorityThreshold float64 `json:"priority_threshold,omitempty"` PriorityDecision string `json:"priority_decision,omitempty"` PriorityProposed int64 `json:"priority_proposed,omitempty"` PriorityWouldChange bool `json:"priority_would_change,omitempty"` PriorityChanged bool `json:"priority_changed,omitempty"` PriorityReasonCodes []string `json:"priority_reason_codes,omitempty"` PriorityChecks []RuleCheck `json:"priority_checks,omitempty"` StatusAnalysisExecuted bool `json:"status_analysis_executed,omitempty"` StatusAnalysisSkipReason string `json:"status_analysis_skip_reason,omitempty"` StatusAnalysisDurationMS int64 `json:"status_analysis_duration_ms,omitempty"` StatusAIReason string `json:"status_ai_reason,omitempty"` StatusReplySelected bool `json:"status_reply_selected,omitempty"` StatusReplyDecision string `json:"status_reply_decision,omitempty"` StatusReplyType string `json:"status_reply_type,omitempty"` StatusReplyCandidateID string `json:"status_reply_candidate_id,omitempty"` StatusReplyCandidateName string `json:"status_reply_candidate_name,omitempty"` StatusReplyCandidateStatus string `json:"status_reply_candidate_status,omitempty"` StatusReplyRelevance float64 `json:"status_reply_relevance,omitempty"` StatusReplyAIConfidence float64 `json:"status_reply_ai_confidence,omitempty"` StatusReplyFinalScore float64 `json:"status_reply_final_score,omitempty"` StatusReplyMinRelevance float64 `json:"status_reply_min_relevance,omitempty"` StatusReplyMinAIConfidence float64 `json:"status_reply_min_ai_confidence,omitempty"` StatusReplyMinFinalScore float64 `json:"status_reply_min_final_score,omitempty"` StatusReplyRenderedText string `json:"status_reply_rendered_text,omitempty"` StatusChecks []RuleCheck `json:"status_checks,omitempty"` StatusCandidates []StatusCandidateAudit `json:"status_candidates,omitempty"` ReplyBasisCategoryID int64 `json:"reply_basis_category_id,omitempty"` ReplyBasisCategoryName string `json:"reply_basis_category_name,omitempty"` PolicyReason string `json:"policy_reason,omitempty"` CategoryChecks []RuleCheck `json:"category_checks,omitempty"` ReplyChecks []RuleCheck `json:"reply_checks,omitempty"` ExecutionChecks []RuleCheck `json:"execution_checks,omitempty"` CategoryBefore int64 `json:"category_before"` CategoryBeforeName string `json:"category_before_name,omitempty"` AIRecommendedCategoryID int64 `json:"ai_recommended_category_id,omitempty"` AIRecommendedCategoryName string `json:"ai_recommended_category_name,omitempty"` AICategoryConfidence float64 `json:"ai_category_confidence,omitempty"` CategoryThreshold float64 `json:"category_threshold,omitempty"` CategoryDecision string `json:"category_decision,omitempty"` CategoryProposed int64 `json:"category_proposed"` CategoryWouldChange bool `json:"category_would_change"` CategoryChanged bool `json:"category_changed"` AIReplyRecommended bool `json:"ai_reply_recommended,omitempty"` AIReplyConfidence float64 `json:"ai_reply_confidence,omitempty"` ReplyThreshold float64 `json:"reply_threshold,omitempty"` AIKnowledgeID string `json:"ai_knowledge_id,omitempty"` ReplyDecision string `json:"reply_decision,omitempty"` ReplyProposed bool `json:"reply_proposed"` ReplyWritten bool `json:"reply_written"` KnowledgeID string `json:"knowledge_id,omitempty"` KnowledgeTopID string `json:"knowledge_top_id,omitempty"` KnowledgeTopTitle string `json:"knowledge_top_title,omitempty"` KnowledgeScore float64 `json:"knowledge_score,omitempty"` KnowledgeSemanticScore float64 `json:"knowledge_semantic_score,omitempty"` KnowledgeTitleScore float64 `json:"knowledge_title_score,omitempty"` KnowledgeLexicalScore float64 `json:"knowledge_lexical_score,omitempty"` KnowledgeKeywordScore float64 `json:"knowledge_keyword_score,omitempty"` KnowledgeCategoryScore float64 `json:"knowledge_category_score,omitempty"` KnowledgeThreshold float64 `json:"knowledge_threshold,omitempty"` KnowledgeEvidenceScore float64 `json:"knowledge_evidence_score,omitempty"` KnowledgeRetrievalFloor float64 `json:"knowledge_retrieval_floor,omitempty"` KnowledgeCategoryAligned bool `json:"knowledge_category_aligned,omitempty"` KnowledgeBestChunk string `json:"knowledge_best_chunk,omitempty"` KnowledgeBestQueryChunk string `json:"knowledge_best_query_chunk,omitempty"` KnowledgeQueryChunks int `json:"knowledge_query_chunks,omitempty"` KnowledgeDocumentChunks int `json:"knowledge_document_chunks,omitempty"` KnowledgeLLMCandidates int `json:"knowledge_llm_candidates,omitempty"` CategoryKnowledgeLLMCandidates int `json:"category_knowledge_llm_candidates,omitempty"` CategoryKnowledgeCandidateCutoff float64 `json:"category_knowledge_candidate_cutoff,omitempty"` KnowledgeCandidateCutoff float64 `json:"knowledge_candidate_cutoff,omitempty"` KnowledgeCandidateMaxGap float64 `json:"knowledge_candidate_max_gap,omitempty"` KnowledgeAuditTopK int `json:"knowledge_audit_top_k,omitempty"` ContextChanges int `json:"context_changes,omitempty"` ContextIncidents int `json:"context_incidents,omitempty"` ContextIssues int `json:"context_issues,omitempty"` ContextDevices int `json:"context_devices,omitempty"` ContextWarnings []string `json:"context_warnings,omitempty"` KnowledgeCandidates []KnowledgeCandidateAudit `json:"knowledge_candidates,omitempty"` CategoryKnowledgeCandidates []KnowledgeCandidateAudit `json:"category_knowledge_candidates,omitempty"` ReplyKnowledgeCandidates []KnowledgeCandidateAudit `json:"reply_knowledge_candidates,omitempty"` ContextDetails []ContextAuditItem `json:"context_details,omitempty"` DryRun bool `json:"dry_run"` Analyses []AnalysisRun `json:"analyses,omitempty"` Error string `json:"error,omitempty"` }