package delivery import ( "time" "github.com/kami/maven/internal/loop" ) // Kind — what's being delivered. nudges and reminders are two delivery paths // (per spec); the kind flows into the nudge table and ack tracking. a nudge // is loop-derived (a rule fired); a reminder is user-stated future intent. type Kind string const ( KindNudge Kind = "nudge" KindReminder Kind = "reminder" ) // Sendable — what a Sink receives. one per channel per dispatch. // // Body is the full phrased message for voice (local — no shoulder-surf // concern beyond who's in the room). Summary is the minimal body for away // channels (ntfy/telegram) — "disk low on homesrv," not detail. away channels // leave the box through your relay; the minimal-body rule stops notifications // from becoming a shoulder-surf exfil surface. messageForChannel picks which // field the sink should display based on Channel. // // RepeatUntilAck — sev4 ops hard on away → telegram repeats until the user // acknowledges. the telegram sink (or daemon repeat driver) consults // ShouldRepeat + AckTracker. other channels are fire-and-forget. type Sendable struct { Channel Channel Kind Kind // Severity — 0 for reminders (they don't carry one). set for nudges so // sinks can adjust behavior (e.g. telegram could escalate presentation). Severity loop.Severity // identification — one set depending on Kind. nudges use RuleName (matches // the nudges table + the feedback loop's RecentOutcomes key); reminders use // ReminderID (matches the reminders table). RuleName string ReminderID int64 // content Body string // voice (local) — full phrased message Summary string // away channels (ntfy/telegram) — minimal, no exfil // repeat-til-ack — only set for sev4 telegram nudges. the ack key is // RuleName (one un-acked repeat stream per rule). RepeatUntilAck bool // Ts — when this sendable was created (the tick time). flows into // RecordNudge and the ack tracker's last-sent. Ts time.Time }