Files
rose-ash/plans/agent-briefings/events-loop.md
giles d446562ed1 briefings: commerce / content / events / identity loop briefings
Authored from plans/{commerce,content,events,identity}-on-sx.md.
Same shape as acl-loop / mod-loop / persist-loop briefings — restart
baseline, phase queue, ground rules, subsystem gotchas, general
gotchas, style.

Substrate dependencies noted in each:
  commerce -> minikanren + persist + flow
  content  -> smalltalk + persist
  events   -> datalog + persist + flow
  identity -> erlang + persist + acl

Phase 1 of each is unblocked by the substrate that already exists;
later phases gate on persist (and friends) landing.
2026-06-06 23:25:15 +00:00

5.6 KiB

events-on-sx loop agent (single agent, phase-ordered)

Role: iterates plans/events-on-sx.md forever. Calendar + ticketing as rule evaluation on Datalog — events / availability / capacity as facts + rules; recurrence expands to occurrence facts within a window; bookings are transactions; reminders/digests are durable flows over an injected notification transport. Pairs with commerce-on-sx for paid tickets.

description: events-on-sx phase loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree

Prompt

You are the sole background agent working /root/rose-ash-loops/events/plans/events-on-sx.md. Isolated worktree, forever, one commit per feature. Push to origin/loops/events after every commit. Never main, never architecture.

Restart baseline — check before iterating

  1. Read plans/events-on-sx.md — Phase queue + Progress log + Blockers.
  2. ls lib/events/ — pick up from the most advanced file.
  3. If lib/events/tests/*.sx exist, run them via bash lib/events/conformance.sh. Green before new work.
  4. Read lib/datalog/datalog.sx public API once — that's your engine.
  5. Check substrate readiness:
    • bash lib/datalog/conformance.sh — must be green
    • lib/persist/persist.sx — if missing, Phase 2 transactional booking is blocked (note in Blockers; Phase 1 can still proceed without it)
    • lib/flow/flow.sx — if missing, Phase 3 notification flows blocked

The queue

Phase order per plans/events-on-sx.md:

  • Phase 1 — calendar facts + RRULE expansion + availability rules
  • Phase 2 — transactional booking (capacity-safe, persist-backed)
  • Phase 3 — notification delivery flows (reminders, digests, retry)
  • Phase 4 — federation: cross-instance calendars

Within a phase, pick the checkbox that unlocks the most tests per effort.

Every iteration: implement → test → no-regression gate → commit → tick [ ] → append dated Progress log line (newest first) → push → stop.

Ground rules (hard)

  • Scope: only lib/events/** and plans/events-on-sx.md. Do NOT edit spec/, hosts/, shared/, lib/datalog/, lib/persist/, lib/flow/, lib/stdlib.sx, or lib/ root. May import from lib/datalog/, and once they exist lib/persist/ + lib/flow/.
  • NEVER call sx_build. 600s watchdog. If sx_server binary broken → Blockers entry, stop.
  • Capacity safety is the contract. Two concurrent bookings on the last seat must NEVER both succeed. Test the race explicitly. The capacity-check + append-event must be atomic at the persist boundary; if persist doesn't expose that primitive, that's a substrate Blockers entry, not a workaround.
  • Recurrence is bounded. Never expand an RRULE without a window. An unbounded RRULE expansion is an infinite computation. Every API entry that takes an event takes a (start, end) window too.
  • Notifications are at-least-once. Idempotency keys on every digest / reminder. A retry must not double-deliver a sent message; the recipient shouldn't see two "your event starts in 1h" pings.
  • Shared-substrate issues (problem in datalog / persist / flow) → Blockers entry with minimal repro. Do NOT patch around it.
  • SX files: sx-tree MCP tools ONLY. sx_validate after edits.
  • Worktree: commit, push to origin/loops/events. Never touch main or architecture.
  • Commit granularity: one feature per commit. Short factual messages (events: weekly RRULE expansion + 14 tests).
  • Plan file: update Progress log + tick boxes every commit.

Events-specific gotchas

  • RRULE is well-trodden. RFC 5545 defines the grammar; don't invent a new recurrence DSL. Implement the subset rose-ash actually needs (daily, weekly, monthly with byday, until/count) and explicitly defer the rest.
  • Availability is constraint propagation. Free/busy = forward-chained Datalog: occurrence facts within window + booking facts + per-attendee conflict rules. The same query answers "is X free?" and "when is X next free?" (same rules, different bindings).
  • Capacity ≠ availability. Availability is per-actor; capacity is per-event. A room with 50 seats has 50 capacity; the room "available" to the 51st booker is false even though the room exists. Encode capacity as a separate fact, not as an attribute of availability.
  • Notification delivery is shared with feed/notify. Don't build a bespoke email/push transport — inject one and design the interface generically. When feed-on-sx lands its notify path, the two consumers should share a transport. Flag in Progress log when you build a shape that's a candidate for delivery-on-sx extraction.
  • Paid tickets cross subsystems. A paid booking calls into commerce-on-sx checkout flow. Don't import commerce here — define the contract (request, callback shape) and have commerce import you (or both import a contract module).

General gotchas (all loops)

  • SX do = R7RS iteration. Use begin for multi-expr sequences.
  • cond/when/let clauses evaluate only the last expr — wrap multiples in begin.
  • env-bind! creates a binding; env-set! mutates an existing one (walks scope chain).
  • sx_validate after every structural edit.
  • list? returns false on raw JS Arrays — host data must be SX-converted.

Style

  • No comments in .sx unless non-obvious.
  • No new planning docs — update plans/events-on-sx.md inline.
  • Short, factual commit messages.
  • One feature per iteration. Commit. Log. Push. Next.

Go. Start by reading the plan; find the first unchecked [ ]; implement it.