Files
Claude 4b49032e52 fix(quartz): merge probe verdicts into the record they replace
Follow-up to #3882, which made RelayReachabilityStore edit a relay's
kind:30166 rather than rebuild it. toDiscoveryEventTemplate was the
remaining co-writer: it builds from the verdict alone, so a consumer
following its own KDoc — sign with the monitor key, insert — wipes
whatever else is on that address, undoing the merge for exactly the
writer #3882 set out to protect.

It now takes the current record and carries across every tag the verdict
did not measure, on the same rules:

- Ownership is per writer, and this one measures more than the store
  does. A write probe determines `pow` from the OK message, so `R pow` is
  its own finding and must not be re-dated from an older record. Without
  a ReadWriteVerdict it never exercised the write path, so the same tag
  is somebody else's and is carried across untouched — hence the
  hasReadWrite flag rather than a fixed set.
- Both polarities of each requirement are owned, so an update cannot
  leave the record asserting `pow` and `!pow` at once.
- created_at is max(requested, current + 1): a store enforcing
  replaceable semantics rejects anything not strictly newer, and the
  probe would be lost with nothing to show for the round trip.

The parameter defaults to null, so every existing caller keeps today's
behaviour and the change is additive.

Test plan: ./gradlew :quartz:jvmTest — 4,081 tests, all passing. Three
new cases in RelayProberFlowTest: a foreign tag and an unmeasured `R pow`
surviving a probe without a write verdict, a stale `R pow` being replaced
when the write path DID run, and the stamp landing past the record it
replaces.
2026-08-08 18:59:17 +00:00
..