#173: page verdict shares FaultsFrom judgement so push and landing cannot disagree

This commit is contained in:
2026-08-23 11:24:09 +07:00
parent a7bbeb50e5
commit 820f57a7fa
3 changed files with 137 additions and 17 deletions
+40 -16
View File
@@ -2,8 +2,10 @@ package web
import (
"fmt"
"log"
"time"
"bookmarkmanager/backend/internal/latest"
"bookmarkmanager/backend/internal/store"
)
@@ -92,7 +94,31 @@ func (h *Handler) overviewView() (overviewView, error) {
view := overviewView{Waiting: waiting(passes)}
view.Unchecked = totals[store.SeriesFilterStale] + totals[store.SeriesFilterNeverChecked]
view.Verdict, view.HasCounts = overviewVerdict(passes, now)
var refusingSince map[string]int64
if m, err := h.store.RefusingSince(now.UnixMilli()); err != nil {
log.Printf("admin overview: refusing since: %v", err)
} else {
refusingSince = m
}
var sidecarOK map[string]int64
if m, err := h.store.SidecarOK(latest.BrowserBackedSites()); err != nil {
log.Printf("admin overview: sidecar ok: %v", err)
} else {
sidecarOK = m
}
var noChapterShare map[string]float64
if m, err := h.store.NoChapterShare(cutoff); err != nil {
log.Printf("admin overview: no-chapter share: %v", err)
} else {
noChapterShare = m
}
faults := latest.FaultsFrom(latest.FaultInput{
Passes: passes,
RefusingSince: refusingSince,
SidecarOK: sidecarOK,
NoChapterShare: noChapterShare,
}, now)
view.Verdict, view.HasCounts = overviewVerdict(passes, faults)
// The hygiene figures, in seriesFilterOrder's tail: the problem filters
// in permanent-then-fixable order, then the informational tail — finished
@@ -165,28 +191,26 @@ func door(label string, count int, href string) fig {
return fig{Label: label, Href: href, Count: count}
}
// overviewVerdict decides the landing page's one line from the latest pass
// per Site: no passes at all is "no Lane has reported yet" — never confident
// zeroes; otherwise the count of Lanes whose last pass needs the owner, or
// "all lanes healthy". The count comes from the same laneState judgement the
// Lanes page colours on, so the two pages cannot disagree on what a fault is.
func overviewVerdict(passes []store.LanePass, now time.Time) (phrase string, counts bool) {
// overviewVerdict decides the landing page's one line: no passes at all is
// "no Lane has reported yet" — never confident zeroes; otherwise the count of
// faults from the shared FaultsFrom judgement, so the page and the push
// cannot disagree. Zero faults is "all lanes healthy". A sidecar-down fault
// carries Site == "" and is still one fault. The Lanes page's per-row
// laneState is a different question (is this Lane's last pass healthy) from
// the notice class, and its known false positives live there deliberately, so
// the two now differ.
func overviewVerdict(passes []store.LanePass, faults []latest.Fault) (phrase string, counts bool) {
if len(passes) == 0 {
return "no Lane has reported yet", false
}
attention := 0
for _, p := range passes {
if _, _, attn := laneState(p, now); attn {
attention++
}
}
if attention == 0 {
n := len(faults)
if n == 0 {
return "all lanes healthy", true
}
if attention == 1 {
if n == 1 {
return "1 lane needs a look", true
}
return fmt.Sprintf("%d lanes need a look", attention), true
return fmt.Sprintf("%d lanes need a look", n), true
}
// waiting sums Due over the latest pass per Site: how many Series the Lanes