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.
118 lines
5.6 KiB
Markdown
118 lines
5.6 KiB
Markdown
# 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 `flow`s 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.
|