Retreat Booking — Discover, set it up, go live, then the guest thread.
The launch-wedge assistant's standing design contract — drawn FROM the shipped
beta flow plus prd-as-retreat-booking.md, for Peyton sign-off. Companion to the
template-agnostic master assistant-flows/assistant-lifecycle.html — this file inherits
it and must not contradict it. Full framing in 1 · Design overview
and 2 · Scope below.
Widths here sample a fluid continuum — content
scales continuously; structure steps only at sm 640 · md 768 · lg 1024. Kit:
design-canon.md U8. Reading order (kit-locked 2026-07-31): § Desktop screens first,
then § Mobile screens — 375, then the 768 tablet sample. 375 is still designed and scored FIRST
in real work.
Every $ figure drawn here ($1.75/run, deposit and balance amounts) is illustrative — prices arrive from props/the DB at runtime, never authored literals (single-source pricing). Demo persona: Salt & Stone Retreats (host Lena), consistent with the on-brand-support.html exemplar. Program: Bali Spring Retreat · Apr 12–19 · 12 spots · 30% deposit.
Retreat Booking takes the payment chase off a retreat host's plate. Guests already ask to book in WhatsApp — this assistant holds the spot, relays the host's own payment link, nudges the deposit, chases the balance at T-30/14/7 in the host's voice, and confirms the booking the moment the money is seen in the host's roster, Stripe, or a one-tap "Mark paid". The host watches it all from one Pulse card and makes every overdue call herself — Mark paid, extend, or release. It is the launch wedge: the retreat-persona card on the shared Program Booking Engine, and the first assistant a retreat host meets. MystFlo never touches the money — it chases, tracks, and confirms only.
20260802012707_rtbk01_rename_cohort_to_retreat.sql; price renders from price_per_run, never authored.payment_mode: deposit_balance is the DEFAULT here (hidden on the workshop card); engine mechanics live in the RTBK01 PRD (the engine home). Sibling card: workshop-booking.html (TMPL-WSBK01).workshop-booking.html.workshop-booking.html sec-13) and the master (assistant-lifecycle.html 8d · 9b-r · 9e); not redrawn here.BYOK_AI_HIDDEN; the AI Model row has no caret (kit lock 2026-08-05).description (card one-liner) · details.tldr · long_description · 4 details.benefits cards (typographic, no icons — T1203) — all VERBATIM from the PRD Catalog Copy table; screens never paraphrase the DB.details.flow "How it works" chart — 6 nodes · 1 branch, deterministic seed; the live seed lags this contract on two counts (gap 5: "cohort" rename + missing chase node).roster_sources (sheet | airtable | stripe + column map) — a read SOURCE, not a storage destination; read at send time, never stored (AC-COHB-06 ↗). No storage role declared (Required storage | — |).payment_mode: deposit_balance default — 30% deposit confirms the hold, balance due T-14.cohort_bookings — never written back to the host's file. States: held → deposit paid → confirmed · overdue → host verdict; ambiguous roster values stay pending, never accidentally paid (AC-COHB-05 ↗).Two journeys, one diagram. The founder's Activate step opens the guest's booking door; every guest payment event flows back as a Pulse row, and the ONLY money-moment MystFlo owns is the $1.75 meter on the paid → confirmed edge. Standard vocabulary: founder Discover → Evaluate → Activate → Monitor → Decide · guest Trigger → Interact → Outcome → Fallback.
FOUNDER JOURNEY ────────────────────────────────────────────────────────────
┌ DISCOVER & EVALUATE ────────────────────────────────────────────────────┐
│ Explore card (sec-1) → detail sheet: what/why/how (sec-1b) │
└─────────────────────────────────┬────────────────────────────────────────┘
▼
┌ ACTIVATE ────────────────────────────────────────────────────────────────┐
│ Personalize — roster + round + payment relay + sign-off (sec-2) │
│ → Connect — WhatsApp · roster source · Brain Check (sec-3) │
│ → Try — readback + one real test reminder (sec-4) → Activated (sec-5) │
└─────────────────────────────────┬────────────────────────────────────────┘
▼ ◄── guests book from here on
┌ MONITOR ─────────────────────────────────────────────────────────────────┐
│ Pulse card — bookings, chase activity, needs-attention rows (sec-6) │
└─────────────────────────────────┬────────────────────────────────────────┘
│ a due date passes unpaid
▼
┌ DECIDE — the host verdict moment ────────────────────────────────────────┐
│ Overdue row: Mark paid · Extend due date · Release spot (sec-6b) │
│ — never a unilateral release (AC-COHB-07 ↗ / AC-COHB-08 ↗) │
└──────────────────────────────────────────────────────────────────────────┘
GUEST JOURNEY ──────────────────────────────────────────────────────────────
┌ TRIGGER ─────────────────────────────────────────────────────────────────┐
│ Guest asks about the retreat in WhatsApp → capture gate: name + email │
│ → spot held pending deposit (sec-7a) — sold-out waitlists instead │
│ (AC-COHB-20 ↗), never a silent overbook │
└─────────────────────────────────┬────────────────────────────────────────┘
▼
┌ INTERACT — the chase, in the host's voice ───────────────────────────────┐
│ deposit nudge (sec-7a) → balance reminders T-30/14/7 with the HOST'S │
│ payment link relayed (sec-7b, AC-COHB-03 ↗) → "I already paid" honest │
│ re-check (sec-7c, AC-COHB-10 ↗) │
└─────────────────────────────────┬────────────────────────────────────────┘
▼
┌ OUTCOME ─────────────────────────────────────────────────────────────────┐
│ payment learned (sheet tick · Stripe event · host Mark paid) → │
│ WhatsApp + email confirmation <30s, booking = confirmed, ONE $1.75 │
│ meter (AC-COHB-04 ↗ · AC-BILL-01 ↗ · AC-BILL-02 ↗) │
└─────────────────────────────────┬────────────────────────────────────────┘
▼
┌ FALLBACK ────────────────────────────────────────────────────────────────┐
│ overdue → ONE notice, reminders HOLD, host pinged (sec-7d) · stale │
│ roster ≥7d → guest sends HELD (AC-COHB-12 ↗) · cancel intent honoured, │
│ no fee (AC-COHB-09 ↗ / AC-BILL-04 ↗) │
└──────────────────────────────────────────────────────────────────────────┘
workshop-booking.html → 3s / 6s, Pulse in assistant-lifecycle.html → 8f.Retreat Booking reads your roster (Google Sheet or Airtable), then runs the entire payment chase on WhatsApp: deposit nudges, balance reminders at T-30/14/7, and overdue handling — all in your voice. It relays your own payment link and tracks who's paid from your roster or your "mark paid" tap — MystFlo never touches the money. You decide every release from Pulse.
Edit what you sell in your Brain →
Same retreat, new round? Just set when and where.
Arrival, or a range with the last day’s end — 15:00 or 15:00–11:00. Empty means nothing is promised in the messages.
Where guests arrive — fills the confirmation and the chase messages. Starts as the offering’s venue from your Brain, or your business address when it has none; change either here if this round is somewhere else. With a map link guests get a one-tap “Open in Maps” button; without it they still see the address.
Edits here change only this retreat — your Brain stays as it is.
Field names match your Brain’s offering fields one-to-one — Name · Price · Date · Time · Where · Spots (Peyton 2026-09-23). Date always starts empty after a pick — same retreat, new round.
Which channels the deposit/balance chase can use — connect the app for each in Connect.
Select; rows name + price · spots, separator, “+ Something new” last). Before a pick nothing else in 01 renders. The Brain asks per offering “One-time or recurring?” (Peyton 2026-09-25 — never inferred from a date) and each dropdown row prints the answer. Recurring (drawn) → standing content fills (Name · Price · Currency · Spots · Where, Where falling back to the business address, #5249 — Where pre-fill on recurring is open for Peyton, chipped in the frame); Date and Time start empty under “Same retreat, new round? Just set when and where.” One-time → everything the Brain has fills, Date · Time · Where included; blanks stay blank; no hint. Not answered yet → fills whatever the Brain has, no hint. “+ Something new” reveals the fields empty. Nothing in the Brain → no dropdown, empty fields. Full state set drawn on workshop sec-3.OfferingPicker (row grammar now the dropdown above — formerly radio rows over brain_profile.services[], price sub-line, ✓ on the pick, “+ Something new” dashed) now sits ABOVE Name · Price + Currency · Date (a range) · Time (optional — arrival, end optional) · Where (address, map link beneath; prefilled from the offering’s venue or else the business address, always shown, #5249) · Spots — the shared Brain offering vocabulary, one-to-one (Peyton 2026-09-23; a retreat is a program in that vocabulary, so Where + Time ride here too; “Retreat name” / “Cohort name” → Name, “Dates & spots” split into Date + Spots) — which stay visible and editable after a pick; today COHORT_PICKER_FIELD_KEYS (ConfigureStep.tsx:267) removes name + price from the form once picked — that removal is what this frame retires. A pick fills wizard configuration only; the one quiet line under Spots says the Brain is untouched. Dates stay per-round, never quick-filled. AC-COHB-01 ↗ (3-tier model) still holds; the “stays editable” clause is NEW (PRD debt) for prd-as-retreat-booking.md’s Tier-2 sentence. Where + Time follow the Workshop/Event contract exactly (AC-COHB-28 ↗ · AC-COHB-31 ↗ name this card — but the #4478 schema patch skipped RTBK01, so both fields are specified-not-built here: the build adds them to configuration_schema, it does not unhide them); only the Try-step “Add it to what you sell?” row stays drawn on the siblings, not here (scope per Peyton)..panel — no true 1180-width realization existed anywhere in this file (this file's own "desktop" convention tops out at .panel-wide, 720px — see sec-1b/sec-2). Re-drawn here at the file's own pre-defined .desktop 1180 class (present in the stylesheet, previously unused) using this file's own header chrome (.m-head/.ttabs.pre-stepper, not the foreign `.sheet-top`/`.reveal` pattern from other mockups) plus the master's two-column split (apps left flex-1, Brain Check right 400px — `assistant-lifecycle.html` sec-5). Same rows/copy as before, nothing invented.roster_sources: sheet | airtable | stripe + column map, read at send time, never written back — AC-COHB-06); the label change doesn't imply a write path was added. No caret — the source is bound in Personalize, not a Connect-tab picker.cohort_bookings gets its OWN row (the new row above, badge "MystFlo Storage"), not merged into the roster row's badge. Read source and write destination are different mechanisms and now render as two distinct rows, matching WSBK01's own storage role shape byte-for-byte (providers: ["mystflo_storage"], single provider). Shipped: `required_roles` migration seeding `chat` + `storage` roles for TMPL-RTBK01 (previously `[]`, legacy-fallback-only) — this is the full cutover onto the required-roles schema, since `useRoleMode` is all-or-nothing; the legacy "Google Account" app requirement is dropped (no roster-picker UI exists to gate on it yet, zero live instances at migration time) and tracked as separate follow-up work, not silently lost.required_roles entry backs it — roster_sources has no frontend picker built), so today's real Connect tab shows only ONE row saying "Storage," not two.assistant-lifecycle.html #sec-5c. Header is amber Complete Setup because Payment is Reconnect (Connect incomplete). Once Connect is done this slot becomes quiet Continue to Try — a Brain blocker does not keep the amber label. Ready-to-run bar: Apps · Wallet · Brain. Wallet pending (label, no glyph) while the card hook loads — not drawn here; see master #sec-5c.Test it — unchanged from frame 4 (one real reminder to your own WhatsApp · roster-shape notice).
Both run on your WhatsApp from the moment you activate. Each is charged only when used.
3 guests already owe a balance — the first reminders are scheduled for tomorrow 9am, their time.
Edit what you sell in your Brain →
Same retreat, new round? Just set when and where.
Starts as the offering’s venue from your Brain, or your business address — change either if this round is somewhere else.
Edits here change only this retreat — your Brain stays as it is.
Field names match your Brain’s offering fields one-to-one — Name · Price · Date · Time · Where · Spots.
Test it — unchanged from frame 4 (one real reminder to your own WhatsApp · roster-shape notice).
Both run on your WhatsApp from the moment you activate. Each is charged only when used.
assistant-flows/assistant-lifecycle.html is the primary structural contract; assistant-flows/workshop-booking.html is the engine sibling AND the canonical structural reference (design-canon.md § "Assistant-flow mockup structure — 8-section shape", Peyton-locked 2026-08-06); token block borrowed verbatim from on-brand-support.html.prd-as-retreat-booking.md §Test Plan (AC-COHB-* / AC-BILL-* / AC-SIGNOFF-*) · rename migration 20260802012707_rtbk01_rename_cohort_to_retreat.sql · _shared/chat-handler.ts booking engine · AttentionPanel.tsx verdict gating · ledger ../parity/parity-retreat-booking.md.Mark paid confirms her and sends the confirmation · Extend picks a new date and resumes reminders · Release frees the spot and tells her kindly.
booking_keywords hidden). Not redrawn here on purpose.wa.me/…?text= + Copy, short wa.me/{digits} + Copy short, QR + Download QR) and its not-connected state ("Connect WhatsApp to generate your booking link and QR") are the same component as every booking-type sibling — drawn once at the master, not forked per assistant.assistant-lifecycle.html sec-9d (build gap, pending #3120).?assistant=<id>&records=open. Read + verdict only — the verdict set stays exactly Mark paid · Extend · Release; no editable cells ever (an editable row is a CRM). Frames live on the engine home (workshop-booking.html sec-13) and the master (8d · 9b-r · 9e); not built.Parity ledger: ../parity/parity-retreat-booking.md · PRD: docs/product/assistants/shared/prd-as-retreat-booking.md · Engine sibling: workshop-booking.html · Master: assistant-lifecycle.html