feat(feedback): enhance false positive explanations with diagnostic context

When users mark detections as incorrect, the system now provides:
- Contributing link name (MAC prefix)
- DeltaRMS value and threshold ratio
- Root cause from diagnostic checks
- Note about applying corrections

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-04-25 12:11:12 -04:00
parent 5d0feaeaa6
commit af5101e9e4
2 changed files with 36 additions and 7 deletions

View file

@ -1193,7 +1193,7 @@
const explanation = eventData.explainability;
const contributingLinks = explanation.contributing_links || [];
const allLinks = explanation.all_links || [];
const diagnosis = explanation.diagnosis || null;
// Find the primary contributing link
const primaryLink = contributingLinks.length > 0 ? contributingLinks[0] : null;
@ -1209,13 +1209,13 @@
explanationText = `The system detected motion here because: <strong>${linkName}</strong>'s signal (deltaRMS: ${deltaRMS}) exceeded the motion threshold by <strong>${ratio}x</strong>.`;
// Add root cause from diagnostic if available
if (primaryLink.diagnosis) {
const diagnosis = primaryLink.diagnosis;
if (diagnosis) {
explanationText += `<br><br><strong>Possible cause:</strong> ${diagnosis.detail}`;
if (diagnosis.advice) {
explanationText += `<br><strong>What to do:</strong> ${diagnosis.advice}`;
}
explanationText += `<br><br><em>We've noted this and will apply corrections.</em>`;
} else {
explanationText += `<br><br><strong>Possible cause:</strong> Ambient RF interference or environmental changes. We've noted this and will apply corrections.`;
}

View file

@ -3,6 +3,7 @@ package api
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
@ -174,7 +175,21 @@ func (h *FeedbackHandler) handleSubmitFeedback(w http.ResponseWriter, r *http.Re
// We'll use the blob ID to get the explanation
// Get explanation from the handler directly
if exp := h.getExplainabilityForBlob(req.BlobID, timestamp); exp != nil {
// Build explainability response
// Build contributing links data with detailed information
contributingLinksData := make([]map[string]interface{}, 0, len(exp.ContributingLinks))
for _, link := range exp.ContributingLinks {
linkData := map[string]interface{}{
"link_id": link.LinkID,
"node_mac": link.NodeMAC,
"peer_mac": link.PeerMAC,
"delta_rms": link.DeltaRMS,
"zone_number": link.ZoneNumber,
"weight": link.Weight,
"contributing": link.Contributing,
}
contributingLinksData = append(contributingLinksData, linkData)
}
explainabilityData := map[string]interface{}{
"blob_id": exp.BlobID,
"x": exp.X,
@ -182,8 +197,7 @@ func (h *FeedbackHandler) handleSubmitFeedback(w http.ResponseWriter, r *http.Re
"z": exp.Z,
"confidence": exp.Confidence,
"timestamp_ms": exp.Timestamp,
"contributing_links": exp.ContributingLinks,
"all_links": exp.AllLinks,
"contributing_links": contributingLinksData,
}
// Add diagnostic info for primary contributing link
@ -206,7 +220,22 @@ func (h *FeedbackHandler) handleSubmitFeedback(w http.ResponseWriter, r *http.Re
// Update the inline response message with diagnostic context
if diagnosis.RuleID != "no_issue_detected" && diagnosis.RuleID != "insufficient_data" {
inlineResp["message"] = diagnosis.Detail + " " + diagnosis.Advice
// Build a more detailed explanation message
linkName := linkID
if len(primaryLink.NodeMAC) >= 8 {
linkName = primaryLink.NodeMAC[:8]
}
deltaRMS := primaryLink.DeltaRMS
threshold := 0.02
ratio := "1.0"
if threshold > 0 {
ratio = fmt.Sprintf("%.1f", deltaRMS/threshold)
}
explanationMsg := fmt.Sprintf("The system detected motion here because: %s's signal (deltaRMS: %.4f) exceeded the motion threshold by %sx. ",
linkName, deltaRMS, ratio)
explanationMsg += diagnosis.Detail + " " + diagnosis.Advice + " We've noted this and will apply corrections."
inlineResp["message"] = explanationMsg
}
}
}