Files
meshcore-analyzer/cmd
bot 841fc5def7 fix(#1229): GREEN — source-diversity confidence weighting in tier-1 resolver
Option C from issue #1229: weight neighbor-graph edges by the number of
distinct observers that contributed to them, so the disambiguator
prefers corroborated edges over single-source ones at the same raw
score. Stacks with the geo-rejection filter merged for #1228 to give
two independent defenses against cross-region prefix-collision
pollution.

Formula (NeighborEdge.Confidence):

    c = min(1.0, max(1, |Observers|) / 3.0)

  - 1 observer  -> 1/3 weight (suspect)
  - 2 observers -> 2/3 weight
  - >=3         -> 1.0 (saturated, full historical weight)

  Saturation at 3 is conservative: high enough that a single chatty
  observer cannot dominate, low enough that 3-observer corroboration
  in a normally-staffed region already counts as full confidence.

Tier-1 score in resolveWithContext becomes Score(now) * Confidence().
The downstream ratio guard (best >= 3x runner-up) is unchanged — a
6-observer edge with 30 obs now beats a 1-observer edge with 25 obs by
3.6x (vs. 1.2x before), enough to trigger tier 1 and skip the geo
fallback that was misresolving in the cross-region case.

The Observers map[string]bool field already existed on NeighborEdge
and was populated on every upsert; this PR is the first to consume it
in the resolver.

Backward compatibility (persistence): neighbor_edges schema is
unchanged. The Observers set is rebuilt by BuildFromStoreWithOptions
from live observations on every graph refresh (5-min TTL), so persisted
edges only carry a stale empty set during the warm-up window after a
restart. Confidence() defaults n to 1 when |Observers|==0, so legacy
rows resolve as single-observer (degraded but non-zero) confidence
rather than disappearing — defensive.

Fixes #1229
2026-05-16 19:45:50 +00:00
..