Red commit: 5ffdf6b07c (CI run: pending —
see PR Checks tab)
Fixes#1197
## What this changes
Two-part fix matching the issue spec:
1. **Tier-3/4 tiebreak by observation count, not slice order**
(`store.go` resolver + `getAllNodes`).
- Plumbs `nodes.advert_count` → new `nodeInfo.ObservationCount` field
via the existing `getAllNodes` query (graceful fallback when the column
is absent on legacy DBs).
- `resolveWithContext` tier 3 (GPS preference) now picks the GPS-having
candidate with the highest observation count.
- Tier 4 (no-GPS fallback) likewise picks by observation count instead
of `candidates[0]`.
2. **Plumb hop-context to the resolver** at all four call sites called
out in the issue.
- New `buildHopContextPubkeys(tx, pm)` collects: sender pubkey from
`tx.DecodedJSON.pubKey`, observer pubkey from `tx.ObserverID`, plus
unambiguous-prefix anchors (single-candidate prefixes in the path).
- Wired into the four sites: broadcast distance compute (~1707),
recompute-on-path-change (~2944), `buildDistanceIndex` (~2982),
`computeAnalyticsTopology` (~5125).
- Per-tx hop caches were moved inside the per-tx loop on the distance
paths since context now varies per tx (was safely shared before only
because every caller passed `nil`).
- `computeAnalyticsTopology` aggregates context across the analytics
scan rather than per-tx because `resolveHop` is called outside the scan
loop downstream.
## Tests
Red→green pairs visible in the commit history:
- Pair A — tier-3 observation-count tiebreak
(`TestResolveWithContext_Tier3_PicksHigherObservationCount`).
- Pair B — context plumbing
(`TestBuildHopContextPubkeys_IncludesSenderAndUnambiguousAnchors`) +
tier-2 geo-proximity
(`TestResolveWithContext_Tier2_PicksGeographicallyCloserCandidate`).
`go test ./...` green on `cmd/server`.
## Out of scope (per issue)
300 km hop cap, API confidence/alternative-count surfacing, firmware
prefix-collision space — all explicitly excluded in #1197.
---------
Co-authored-by: openclaw-bot <bot@openclaw.local>
Co-authored-by: corescope-bot <bot@corescope.local>
Co-authored-by: Kpa-clawbot <bot@kpa-clawbot.local>