Take only acknowledgements from a desk click, and make each answer a one-time ticket
mesh/merge-gate pass: builds dunst, messenger → g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group fix/notifications-after-review ready: every member ready, and composed together they pass
mesh/delivery superseded: a newer head of the same pull request

Review found that any process of the operator's account can choose a dunst action,
so a click could release or stop a delivery in the operator's name; that tokens
lived for ever; that a warning's answers died in ten seconds; and that a restarted
notifier left dead buttons (hq ADR 0258).
This commit is contained in:
jochen
2026-10-08 14:38:24 +02:00
parent 541b24d96e
commit d83711f11e
19 changed files with 616 additions and 137 deletions
+5
View File
@@ -57,12 +57,14 @@ func (h *Holder) Sync(open []Condition, asked time.Time) SyncResult {
old := h.open[c.Key]
var r *Record
known := old != nil
wasQuiet := false
switch {
case old != nil && old.Seen.After(asked):
h.mu.Unlock()
res.Skipped = append(res.Skipped, c.Key)
continue
case old != nil:
wasQuiet = needsNothing(old) && !old.told()
if !old.Cleared.IsZero() {
// Ended here, open there: back to open, quietly — the reading is not an event.
old.Cleared = time.Time{}
@@ -98,6 +100,9 @@ func (h *Holder) Sync(open []Condition, asked time.Time) SyncResult {
urgent = append(urgent, r)
case !known && now.Sub(r.Raised) <= FreshFor:
fresh = append(fresh, r)
case wasQuiet && !needsNothing(r):
// Kept quiet as needing nothing; its words now need the operator (ADR 0258).
fresh = append(fresh, r)
default:
res.State = append(res.State, r.Key)
}