events: notification delivery flows on lib/flow + 7 tests (Phase 3 start)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s

notify.sx: reminders + digests as durable flows over an injected transport.
A flow requests delivery (suspend); the host dispatch sends and resumes with
the outcome. At-least-once + idempotent (transport dedups by msg id; replay
logs outcomes). Retry rides suspend/resume with distinct per-attempt tags,
bounded by maxn. Digest delivers a batch with per-message outcomes.
182/182 green. Delivery core is the delivery-on-sx extraction seam.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 04:02:54 +00:00
parent 05d5c46730
commit e35769411e
6 changed files with 154 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ capacity rules, transactional booking, and a flow-driven notification dispatcher
## Status (rolling)
`bash lib/events/conformance.sh`**175/175** (Phase 1 + Phase 2 complete: booking/holds/paid-ticket contract)
`bash lib/events/conformance.sh`**182/182** (Phases 1-2 + Phase 3 notification delivery flows)
## Ground rules
@@ -70,11 +70,13 @@ lib/events/api.sx ── (events/schedule) (events/book) (events/agenda) ──
- [x] tests: capacity edge, double-book guard, conflict detection
## Phase 3 — Notification delivery (flow)
- [ ] `notify.sx` — reminder/digest flows over injected transport
- [ ] retry/backoff on transport failure (flow suspend/resume)
- [ ] tests: delivery success, retry path, idempotent re-send
- [x] `notify.sx` — reminder/digest flows over injected transport
- [x] retry/backoff on transport failure (flow suspend/resume)
- [x] tests: delivery success, retry path, idempotent re-send
- [ ] wire reminders to occurrences (schedule "starts in 1h" from agenda)
- [ ] NOTE: shared with `feed/notify` — candidate for later extraction to a
`delivery-on-sx` once a second consumer is real
`delivery-on-sx` once a second consumer is real. **Delivery core
(request→dispatch→resume, idempotent, bounded retry) is the extraction seam.**
## Phase 4 — Federation
- [ ] cross-instance events (peer calendar) — trust-gated stub
@@ -82,6 +84,18 @@ lib/events/api.sx ── (events/schedule) (events/book) (events/agenda) ──
## Progress log
- 2026-06-07 — **Phase 3 start: notification delivery flows.** `notify.sx`:
reminders + digests as durable `flow`s over an INJECTED transport (the host
`dispatch`). A flow `request`s delivery (suspend), the host sends and resumes
with the outcome; flow's replay log means a completed send is never re-run on
recovery. At-least-once + idempotent: messages carry an id; the transport
dedups (re-send is a no-op that still reports ok) and replay logs each
outcome. Retry rides suspend/resume — each attempt uses a DISTINCT tag
`(deliver <id> <n>)` so replay stays correct; dispatch returns (ok) /
(retry reason), bounded by maxn → (failed id reason). Digest delivers a batch
with independent per-message outcomes. Authored as Scheme flow source run via
`ev/notify-run` (scheme + flow substrate preloaded). +7 tests, 182/182 green.
Delivery core is the `delivery-on-sx` extraction seam for feed/notify.
- 2026-06-07 — **Phase 2 complete: paid-ticket contract.** `ticket.sx` defines
the two wire messages between events and commerce — `checkout-request`
(events→commerce) and `payment-result` (commerce→events, :paid/:failed/