Design preview · Assistant lifecycle — master structure · #2627 · re-grade 2026-08-17 · funds-first Connect 2026-08-18 · Brain Check door → the real Book + Teach bar 2026-09-10 (#4714, frame 5d)

The generic assistant, every surface of its life

The generic assistant path — Discover through Live, then Guest on the phone.

SizePortrait scrolls 375 · sideways is a slide deckNotes
Design brief — overview · scope · journey (closed)

The template-agnostic MASTER build contract for every surface an assistant passes through — in the 8-section shape (design-canon.md § “Assistant-flow mockup structure”) the five per-assistant flow files inherit.

card → live → monitored → reactivated pre: Overview → Personalize → Connect → Try · post: Pulse → Overview → Personalize → Connect mobile 375 default · desktop 1180 for seated sheets & splits · tablet 768 progressive status color = exceptions only · white glows only

Widths here sample a fluid continuum — content scales continuously; structure steps only at sm 640 · md 768 · lg 1024; radius/hairlines/pills never scale. Kit: design-canon.md U8.

1 · Design overview ↑ top

This file is the canonical, template-agnostic structure an assistant moves through on MystFlo — every surface of its life, regardless of which template it is: the Explore pre card → share → Team → the pre detail sheet (Overview → Personalize → Connect → Try) → activation and its five real outcomes → the Pulse wall, status ladder, Needs your attention inbox (8c) and post detail sheet → edit-class gating while live → “Waiting on you” → reactivation → the split → Billing. It is the PRIMARY build contract for these surfaces (mockup-artifact-first): the numbered archetypes in docs/design/archetypes/ are the per-frame pass-bar, and the five per-assistant flow files in this folder inherit this file's structure and must not contradict it. Frames are drawn on On-Brand Support (TMPL-9P3X) as the worked example — that content is illustrative; the structure, slots and locks are the contract.

2 · Scope ↑ top
In this master — the template-agnostic layer
  • Every generic lifecycle surface and cross-cutting mechanic: pre/post cards and detail sheets, the share sheet, the wizard tabs, the five activation outcomes, the Pulse wall + status ladder, edit-class gating (A6), the pending-action row (R31), reactivation (R18/R19), the split (R35), and the assistant-facing Billing rows.
  • The locks that hold for every assistant: identity (D4), status + wallet language (D-3), fixed-slot anatomy (R34/R13), price slot (R27), app-chip grammar (R24/R15/B1), Brain Check's one home (D-1).
Not here — per-assistant flow files
  • Template-specific Personalize fields and copy, guest-side WhatsApp lanes, records surfaces, per-assistant pricing and catalog copy, and each PRD's own ACs — those live in on-brand-support.html · program-launch-kit.html · retreat-booking.html · waitlist-launch.html · workshop-booking.html, each against its own prd-as-*.md.
Not here — sibling surface files
  • Full page chrome for the host surfaces: Explore (explore.html), Team (team.html), Pulse (pulse.html), Billing (billing.html), Brain (brain.html), Connects hub (connects.html). This file draws the assistant-owned cards/sheets seated in those pages only as far as the lifecycle needs; the pages themselves are those files' contracts.
3 · Content structure ↑ top
The recurring shapes every screen is built from
  • Instance identity (D4) — post-activation, instance name + ASST-* id lead everywhere (cards, sheets, usage rows); template name steps down to the sub-line. Pre-activation surfaces carry template identity (TMPL-*).
  • Component taxonomy (BINDING) — two-phase lifecycle: pre card/sheet (Explore, Team Saved) vs post card/sheet (Pulse, Team Permanent). Once activated → always post.
  • Status ladder (D-3) — one sub-status vocabulary drives every visual: Active · Paused · Stopped · Failed; amber = wallet-empty / needs-you, red reserved for Failed. Status is a dot, never a shape change.
  • Fixed-slot anatomy (R34 · R13) — pre and post cards share one geometry; contexts swap slot content, never slot existence; empty slots keep their space.
  • Price (R27) — plain monochrome text, one wording (“$0.50 per session”), one slot per surface — never a pill.
  • App chips (R24 · R15 · B1) — readiness grammar: max 3 + +N doorway; sort required-not-connected first; verbs Reconnect / Pending only; never a cost signal.
  • Edit classes (A6) — every post-activation field is Safe (edit while Active) / Structural (pause to change) / Identity (start fresh only).
  • Activation outcomes (R12) — the five outcomes the real activate-assistant pipeline produces, drawn as full states, not a spinner.
4 · User journey — full ↑ top
FOUNDER LANE — one generic assistant, six phases · numbers = this file's frames

 §1 DISCOVER          §2 SET UP                    §3 ACTIVATE        §4 LIVE
┌────────────────┐   ┌────────────────────────┐   ┌───────────────┐   ┌─────────────────────┐
│ 1  Explore     │   │ 3     Overview         │   │ 7  Activation │   │ 8   Pulse wall      │
│    pre card    │──►│ 4a·4b Personalize      │──►│    five       │──►│ 8b  status ladder   │
│ 1b Share       │   │       (phone·browser)  │   │    outcomes   │   │ 9·9b·9e post sheet  │
│ 2  Team        │   │ 5·5b  Connect+pickers  │   │    (R12)      │   │ 10·11 post tabs     │
└────────────────┘   │ 6     Try              │   └───────────────┘   │ 12  Waiting on you  │
                     └────────────────────────┘                       └──────────┬──────────┘
                                                                                 │ pause · stop
 §6 MONEY                        §5 CHANGE                                       ▼
┌─────────────────────┐   ┌───────────────────────────────────────┐
│ 15 Billing rows     │◄──│ 13·13b Reactivation                   │◄──────── from §4
│    wallet · usage   │   │ 9c·9d·13c·13d Edit-class gating (A6)  │
│    by assistant     │   │ 14 The split — apps · funds · Brain   │
│                     │   │ 14d Share rises inside the Brain pane │
└─────────────────────┘   └───────────────────────────────────────┘

 pre detail tabs:   Overview → Personalize → Connect → Try        (frames 3–6)
 post detail tabs:  Pulse → Overview → Personalize → Connect      (frames 9–11 · 9c · 9d)

Phase vocabulary: no single PRD locks a journey for the template-agnostic master, so this file uses the canon U10 fallback order — discover → set up → activate → live → change → money — which is also section 6's §1–§6 grouping. Per-assistant flow files reproduce their own PRD's journey diagram verbatim instead. The lifecycle state machine itself (activate → run → pause/resume/stop → reactivate, every transition audited and billed) is owned by prd-pl-assistant-lifecycle.md; the pre-tab pipeline by prd-pl-activation-wizard.md.

Part I — Active sections 5–7 · the build contract, in lifecycle order
Discover
dimmed Explore peeks — revealGap · app header stays visible above (C1)
Share this assistant
Send it to someone who should see it.
✕
What they'll see
AssistantOn-Brand Support
What it doesAnswers guest questions in WhatsApp from your Brain — and hands you the rest.
Price$0.50 per session
Link
platform.mystflo.com/explore/on-brand-support/TMPL-9P3X
Copy Share with…
Or send it straight to
WhatsApp X Threads Copy link

Whoever opens it lands on a preview of this assistant — they can look around without an account.

R25 — `ShareSheetModal`, restyled
  • Kept unchanged: link (`/explore/<slug>/<template-id>` via `createShareLink`), Web Share API sheet (mobile, `navigator.share`), Copy, guest mode's honest line.
  • Files: `ShareSheetModal.tsx` · `shareService.ts` · `ShareRedirect.tsx` · `ShareButton.tsx`.
R33 — Destinations Peyton-locked 2026-07-23
  • Locked to four: WhatsApp · X · Threads · Copy link — Telegram/LinkedIn/Email removed from `ShareSheetModal.tsx` source, not just undrawn.
  • Intents (verbatim): `wa.me/?text=` · `twitter.com/intent/tweet?url=` · `threads.net/intent/post?text=`.
  • No Instagram button (no link-share URL intent exists) — native Share with… still surfaces it by OS name on mobile.
Presentation + content order
  • SHEET on both tiers (not the shipped desktop `Dialog`) — mobile bottom sheet, desktop seated sheet.
  • Chrome: full-width `.sheet-header` band, 44×44 ✕ at the page gutter, 720px work column.
  • Entry point: ⤴ icon beside the heart on pre cards (frames 1, 2).
  • Order: recipient preview (name, one-liner, price) → link + Copy → destinations → one line that it's a guest preview, no account needed.
Build
  • Desktop share opens as a sheet, not a `Dialog`; destination row renders exactly four buttons with the intents above; Telegram/LinkedIn/Email removed from source, not hidden by a flag.
768 not yet drawn for this flow. Desktop and 375 are the contract.
§1 · Discover
1Explore — one pre card, three CTA contexts
Never activated
On-Brand Support
⤴♡
Your business answers DMs in your voice, 24/7 — without you typing a word.
$0.50 per session WhatsApp BusinessMystFlo AIGoogle Sheets+2
Personalize Connect Try
tap for detailsActivate
Currently live
On-Brand Support
⤴♥
Your business answers DMs in your voice, 24/7 — without you typing a word.
$0.50 per session 5 connected
Running as “Autumn retreat support” since Jul 21
View in Pulse
Ran before, stopped
On-Brand Support
⤴♥
Your business answers DMs in your voice, 24/7 — without you typing a word.
$0.50 per session WhatsApp BusinessMystFlo AIGoogle Sheets+2
Ran Apr–Jun · your setup is saved in Past
Reactivate
Component taxonomy BINDING · R34 — Card anatomy
  • All three CTA contexts are ONE pre-activation component — CTA is context-aware (Activate / View in Pulse / Reactivate); never a different shell.
  • Fixed-slot zone map, same height on all three: title (2-line) → desc (2-line) → price → app-chip row (reserved even when content swaps) → progress/status row (stepper OR “Running as…” OR “Ran…”) → CTA pinned bottom.
  • Live card's “5 connected” renders as a chip pill in the same slot, not bare text — row never shrinks.
R1 · R2 · R3 — Card content
  • Details → text link deleted — card tap + “tap for details” pill already carry the doorway (amends shipped `AssistantSummaryCard.pre.tsx`).
  • Category tag chip and task-count chip removed — meta row is price + apps only.
  • Share icon (⤴) beside the heart opens the existing `ShareSheetModal` flow.
R24 · R15 · B1 — App chips
  • Max 3 chips + `+N`; `+N` opens the Connect tab (never a tooltip/hover stack).
  • Sort: required-not-connected → required-connected → storage → optional.
  • Post-activation inverts: unhealthy only + “N connected” quiet line.
  • Never a cost signal (app costs bill to the founder's accounts); verbs: Reconnect / Pending only.
  • Amber = needs you · neutral+green dot = ready · `+N` = doorway · guest sees all-neutral.
R27 · R13 — Price + shared geometry
  • Price is plain text, never a pill — full wording “$0.50 per session”, one slot (first item of the meta line here; its own line under the tldr in detail sheets).
  • Pre/post cards share ONE geometry — same width/min-height, fixed zone map, empty zones keep their space.

Archetype: assistant-summary-card.md.

1bShare the assistant — the shipped flow, restyled — mobile shipped · R25
375 · bottom sheet — link ready
dimmed Explore peeks — tap to return
Share this assistant
Send it to someone who should see it.
✕
What they'll see
AssistantOn-Brand Support
What it doesAnswers guest questions in WhatsApp from your Brain
Price$0.50 per session
Link
platform.mystflo.com/explore/on-brand-support/TMPL-9P3X
Copy
Share with…
Or send it straight to
WhatsApp X Threads Copy link

Whoever opens it lands on a preview of this assistant — they can look around without an account.

375 · generating the link (first moment the sheet opens)
dimmed Explore peeks — tap to return
Share this assistant
Send it to someone who should see it.
✕
What they'll see
AssistantOn-Brand Support
What it doesAnswers guest questions in WhatsApp from your Brain
Price$0.50 per session
Link
Making your link…
Copy
Share with…
Or send it straight to
WhatsApp X Threads Copy link

Whoever opens it lands on a preview of this assistant — they can look around without an account.

375 · guest mode — the one honest extra line
Share this assistant
Send it to someone who should see it.
✕
Link
platform.mystflo.com/explore/on-brand-support/TMPL-9P3X
Copy
Links you make while browsing as a guest don't stick around. Sign in and the link keeps working.
Story · acceptance · design notes — shared with the desktop half: frame 1b ↑ (one note, both tiers).
2Team — Saved (pre) vs Permanent (post)
Saved — pre card, heart filled
Waitlist + Launch
⤴♥
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run WhatsApp BusinessEmailGoogle Sheets+1
Personalize Connect Try
Activate
Permanent — post card
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
Lifecycle boundary · A2 · D4
  • Saved = pre card (still deciding); Permanent = post card (once activated, ALWAYS post).
  • Post anatomy: one status badge, icon run-controls, quiet “Details →” doorway, metrics pinned bottom.
  • A2 — both cards resolve to the same `min-height: 220px` zone map (R34 pre + A4 post) — one row, not two weights.
  • D4 — identity flipped: title = instance name + ASST-id, sub-line = template name alone.
R24 — Chips, pre vs post
  • Saved sorts by readiness (unconnected amber first, capped at 3 + “+1”); Permanent drops the chip row for “N connected” once healthy.
Build
  • Both cards render at the shared 220px zone map; post identity always leads with instance name + id.

Archetype: assistant-summary-card.md (both variants).

Evaluate
dimmed Explore peeks — revealGap · app header stays visible above (C1)
On-Brand Support
Answers guest questions in WhatsApp from your Brain — and hands you the rest.
$0.50 per session
✕
Overview› Personalize › Connect › Try
What it does

It reads your Brain — prices, policies, hours, FAQs, and your brand voice — and answers guests in the voice you confirmed. Anything it can't ground in your knowledge gets handed to you.

How it works
01
Customer
“do you have space in September?”Any hour — 11pm included.
02
Brain ✦
Grounds the answer in your facts ✦ AI
03
Assistant
Replies in your voice, in the same thread
tricky ones → routed to you
◎
Outcome
Guest helped, in your voiceYou never typed a word.
Key benefits
Answers while you sleep
Instant replies at the moment guests are deciding.
Sounds like you — because you confirmed it does
Your voice and policies, confirmed by you.
R5 · R6 — “How it works” chart
  • Shipped flow-steps chart (`HowItWorksFlow.tsx`, PR #1184) — never a bespoke rail.
  • Desktop ≥768: horizontal stepped row on one lit hairline, actor eyebrows, one fragment per node, outcome node elevated at the right end.
  • Mobile: vertical rail, branches as drop-line pills, never entering a neighbour column.
  • 4–6 nodes hard cap; AI-skeleton only on genuinely AI nodes.
  • Real sheet chrome both tiers; tab set/order per T1155; Try disabled until earlier tabs complete.
R26 · R27 — Section order + price
  • Both tiers: What it does → How it works → Key benefits, same order (desktop no longer skips the prose).
  • Header sub-line is the skim tldr, never a substitute for the prose section; prose caps ~72ch.
  • Price is its own quiet meta line under the sub-line, plain text, never inside the tldr.
Build
  • Desktop and mobile render identical section order/copy; chart caps at 6 nodes; AI-skeleton only where genuinely AI-generated.

Archetype: assistant-detail-tabs.md.

dimmed page peeks — revealGap · app header stays visible above (C1)
On-Brand Support
Answers guest questions in WhatsApp from your Brain — and hands you the rest.
✕
Overview› Personalize› Connect › Try
How you sound
Warm Host — default Your voice — coming soon

Warm Host: A steady, friendly host who knows the answers and never rushes anyone.

warmkindcalmclearconfidenthonesthelpfulquick to the right answerquietly upbeat
Communication guardrails
Calmnever matches your customer's stress
Confidentplain answers, no hedging
Honestadmits what it doesn’t know and says what happens next
Quietly upbeatmomentum, not hype — takes a “no” gracefully
  • No emojis
  • Replies stay 1–3 sentences
  • One question at a time
  • Prices and dates verbatim from your Brain
  • Every reply ends with a next step
  • Unknown → warm handoff
  • First reply carries a small “✦ AI” mark under it — once, never repeated
⌄ See it in action (9 examples)
Handling rules

What it answers on its own — Brain values are prefilled below.

hours ✕prices ✕availability ✕+ add topic
Greeting (guests see this first) * required
Hey! You've reached Salt & Stone — how can we help?

Full Brain readiness — what's confirmed, what still needs you — lives on Connect →.

Hey! You've reached Salt & Stone — how can we help?
do you have space in September?
Its real reply appears after activation — answers come from your Brain, never faked here
·· preview ··
D-1 — Personalize form
  • Brain Check module deleted here — Connect is its only home (frame 5).
  • How you sound card leads the column (PR #4177, prd-pl-voice-card.md surface (a), AC-SOUND-01/02/08 ↗): display + skin choice only — Warm Host selected, Your voice locked (coming soon) — never a gate, renders from CODE constants (AC-SOUND-09). Shows for chat assistants + content generators. Per-state drawings: on-brand-support.html frames 3/3b/3t.
  • Personalize keeps per-run knobs only: handling-rule chips + greeting, Brain-prefilled, no readiness gate.
  • Pointer line only: “Brain readiness … lives on Connect →”. Never a readiness count, category eyebrow, or Add/Review-in-Brain action here.
R32 — Preview fills the column
  • Preview column runs the full split height; device shell stretches to fill it, top-aligned (never vertically centered) — applies to all four media (4a–4d).
  • Scroll is the simulated surface's own (phone/page), never a second scroll pane in the sheet.
Build
  • Phone medium: form flex-1 + preview fixed 400px, row cap 1040px. Preview default-on; typed greeting renders live, AI reply stays a labeled placeholder. Chip groups pre-seeded (T1209).
Overview› Personalize› Connect › Try
Your signup page
Headline * required
Join the October cohort waitlist
What they get
First pick of dates, 48 hours before everyone else.
Button label
Join the waitlist — sample until you type
⤢
Join the October cohort waitlist
First pick of dates, 48 hours before everyone else.
Join the waitlistsample
·· preview ··
Browser medium · R32
  • Form fixed 440px, preview flex-1, row capped at the 1440px split token — real desktop breakpoints, not a shrunk mobile view.
  • Per-field liveness: typed fields white, untouched fields fall back to a labeled sample (“sample” pill on fallback only).
  • ⤢ expand-to-fullscreen is browser-preview only, never the phone. Fidelity is true (pixel mirror), vs the phone scaffold's representative.
  • R32: preview column + shell fill the full split height, top-aligned; page body scrolls inside the shell.
Build
  • Preview matches the live desktop breakpoint; untouched fields always carry the “sample” pill; ⤢ never renders on the phone scaffold.
dimmed Explore peeks — revealGap · seated sheet
Retreat Booking
Takes the booking, chases the deposit, keeps your roster true.
$0.35 per booking
Complete Setup ✕
Overview› Personalize › Connect› Try
01 · Connect apps — one list of everything it talks to · 2 need you
Communication WhatsApp Business
Where your guests already message you
Your WhatsApp connection expired — sign in again to continue
Reconnect ⌄
Payment Stripe
Takes the deposit and the balance for this booking
Waiting on Stripe to finish verifying your account
Pending ⌄
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
Storage MystFlo Storage ▾
Where your bookings land — this assistant's records list on Pulse. Tap the badge to send them somewhere else.
Connected ⌄
7 connected ✓ — show all⌄

expands in place — Google Sheets · Google Calendar · Gmail · Slack · Shopify · Calendly · Airtable

02 · Wallet
Wallet balanceEach booking draws $0.35 from your prepaid balance $41.20 →
03 · Brain Check
What you sell 1 of 2
⚠Dates & capacity
It needs your retreat dates before it can take a booking
Add in Brain →
✓Prices
Confirmed
Edit in Brain →
How you run 1 of 3
✓Deposit terms
Confirmed
Edit in Brain →
⚠Payment instructions
last updated 4 months ago — worth a glance, doesn’t stop it running
Review in Brain →
○Cancellation windowOptional
Lets it answer “can I move my dates?” on its own
Add in Brain →
5 sections ready ✓show all
! 7 of 10 ready — Dates & capacity needs you before it can take a booking · 2 to review
Try reads this same check back as one line — it never re-asks.
Ready to run Apps ✕ · Wallet ✓ · Brain ✕
Still needed: Slack channel · terms
R7 · D-1 — Brain Check module
  • Connect is the module's ONLY home (deleted from Personalize, frames 4a/4e/11).
  • Category-grouped rows, required first, `Optional` label on recommended, each row opens the 60/40 split at its section. Amended 2026-09-10 (#4714, Peyton): the left pane is the REAL Book with the Teach bar (frame 5d), not the focusSection co-edit form — retired from this door, not deleted.
  • Blocker vs attention glyph split (2026-08-16, AC-BRAINGATE-11) — a real blocker never looks like a harmless row. Loud amber `⚠` + amber `Add/Review in Brain →` is reserved for a genuine blocker (`required` bucket, hard-fail status — Dates & capacity above). A row that's merely worth a glance (`thin`/`stale`, or a `recommended`-bucket hard-fail status — Payment instructions above) gets a muted `⚠` + muted `Review in Brain →`, same tone as a ready row. A never-filled optional field (`recommended` + `missing` — Cancellation window above) keeps its existing quiet dim `○` + muted `Add in Brain →`. Category eyebrow count tints amber only when that category actually holds a blocker (What you sell above), plain when it only holds attention (How you run above).
  • Ready collapses to the all-clear summary; blocked pins the band open, blockers first.
  • Summary honesty (2026-08-15, extended 2026-08-16): blockers say “before it can {verb}” and now NAME the field when there's exactly one blocker (“Dates & capacity needs you before it can take a booking”) rather than a bare count — 2+ blockers fall back to a count (“2 need you before it can {verb}”). A same-check attention row still appends “· K to review”, even alongside a blocker (this frame: 1 blocker + 2 attention → “...before it can take a booking · 2 to review”). Zero-blocker, attention-only (Offerings Optional / stale) reads “it can {verb} · K to review” — never “before it can”; that no-blocker frame is #sec-5c.
  • Try's read-back summarizes it in one line (“Brain: ✓ 7 of 7 ready”).
R10 — App-list overflow
  • ≤5 apps: flat vertical list. >5: needs-action rows surface first, healthy rows collapse to one “N connected ✓ — show all” row that expands in place — never a second screen or pagination.
  • Verbs: Reconnect (founder can fix it) / Pending (waiting on the provider) only.
D3 — Wallet language
  • “Payment” is retired from assistant surfaces — empty wallet reads “Wallet empty — top up to keep running” in amber, never a red payment error.
  • Funds-first doorway (2026-08-18): the balance itself is the tap target — same slide species as Apps / Brain. Connect never carries a Billing link. Card change lives on the Top-up pane's chip (frame 14c).
  • Ready-to-run bar (`ConnectReadyStatus`) is part of this frame — eyebrow Ready to run, then Apps · Wallet · Brain. When Apps is not all-green, a Still needed: line names the leftover (Slack channel · terms) — #3747. Wallet pending (label, no ✓/✗) while the card hook loads — drawn in #sec-5c. A first-paint Wallet ✕ is a FAIL only after the bar has settled.
Header CTA — Complete Setup stays a button
  • This frame’s Connect is incomplete (WhatsApp Reconnect + Brain blocker) → amber Complete Setup. Once Connect is done → Continue to Try (quiet). canActivate → Activate (white). Live → View in Pulse. Full label set: #sec-5c and explore.html #f9.
B2 — Connect-row grammar
  • Descriptive gray line (what this app does for this assistant) is permanent, never replaced.
  • Error (red) / warning (amber) is an ADDITIONAL line in a reserved status-line slot — row height never jumps.
B3 — MystFlo AI row + the Connect-apps three-pattern contract (2026-08-04)
  • One list, no tiers (kit `design-decisions.md` 2026-08-04, Peyton-locked; terminology amended same day): the "Included with MystFlo" badge group is DELETED platform-wide — MystFlo AI and the Storage role are real rows in "01 · Connect apps", using the real verb ledger (Connected / Reconnect / Pending — never "Selected"/"Included"/"Built in").
  • Two DB-enforced roles, three named patterns, routed by where the assistant's output actually lands — never a free choice. The only real role categories are `ai_model` and `storage` (`ROLE_IDS`, `src/types/required-roles.ts` — there is no separate "platform" category): ① AI Model row (`ai_model` role) — any assistant using AI, no per-assistant exceptions; sub is the AUTO sentence ("AI runs on MystFlo — paid per run, no key to set up." — BYOK deleted, #4959 / ADR-037). ② Storage row → MystFlo Storage value — output fully internal (its own records list on Pulse); Connected, sub explains nothing external is needed. Shipped (#3178, closed) — `STORAGE_PROVIDER_KEYS` now includes `mystflo_storage`, rendered by `MystfloStorageRow.tsx`. ③ Storage row → Google Sheets (MystFlo template) value — output is an external file; reuse `DestinationPicker.tsx` verbatim ("Create a new one" default · "Link a sheet I already have" fallback — 2026-05-22 Template-first lock; column-mapping copy narrows to the Link-existing path only). AMENDED by B9 (Peyton, 2026-08-07): ONE Storage row, THREE destination values — MystFlo Storage · Google Sheet · Your Supabase — the row is never duplicated. The badge names the current destination; its ▾ caret expands the three-group picker in place to switch (frame 5b). The earlier treatment — a second dimmed "Not needed" Storage row holding the inactive value — is RETIRED; the alternatives live inside the dropdown, not as sibling rows.
  • CLOSED (Peyton-locked 2026-08-04, decision-aid Option C) — the label/badge split IS the shape, both roles: row LABEL = the role ("AI Model" / "Storage"), BADGE/value = the connected app ("MystFlo AI" / "Google Sheets" / "MystFlo Storage"), status "Connected" — never "Included". This RETIRES the shipped #2576 C7 title-only treatment ("MystFlo AI" as the row's own title) and overrules PLK's earlier no-AI-row note; AC-EXPLORE-08's "included" chip is fixed in the same pass. Kit: `design-decisions.md` 2026-08-04 closing amendment.
  • External sheet/roster connections stay READ-ONLY by default — no write-back model without a separate explicit ruling; read-only rows pair with the two clarity notes (no info until next read · any table structure works, founder maps her own columns, missing column pauses with a named-column message).
  • TWO standalone controls per row (pass 2, Peyton 2026-08-09 — see frame 5b; supersedes the 2026-08-07 structural-caret amendment). Control 1 = the badge (WHICH apps are in play, default seeded from Personalize/channel choices); control 2 = the status button (connection lifecycle only — Connect white/no-chevron → Connected ⌄ → Reconnect ⌄ → Pending ⌄, disconnect/reconnect in ITS menu). The badge carries a caret ONLY when ≥2 apps are actually in play for that role — real alternatives, or several connected at once. Single-app rows get no caret and NO ⊘ coming soon placeholder (that affordance is deleted, not stubbed). Today with a caret: Storage (3 destinations) · Waitlist+Launch Communication (WhatsApp + Resend). Without: this frame's Communication and Payment, Alerts, AI Model.
  • Pass 3 (Peyton 2026-08-10) — one control species, and an impossible action is greyed, never removed (frame 5b). The status button's chevron sits INSIDE the pill and is present on EVERY connected row including AI Model, because control 2 always has an answer — including "you can't do this, here's why", on an always-visible line, never a hover tooltip. This does NOT touch the badge rule above: control 1 answers "which app?", and with one app in play the expanded list would restate the collapsed badge, so its caret stays deleted. One test governs both: does opening it tell her something the collapsed state didn't?
  • BYOK is deleted (#4959 / ADR-037), not a post-launch reopen. AI Model never crosses a ≥2 threshold. F3 is a tombstone. No caret. Ever.
R35 — Split doorway
  • 01 Apps → Connects page (app's row) · 02 Funds → Top-up pane (amount + card chip — never the Billing page) · card chip on Top-up → Billing page (card change only) · 03 Brain → Brain page (that section — since 2026-09-10 the real Book + Teach bar, frame 5d). Nested `ConnectionModal` retired on the Reconnect path. Full mechanic: frames 14 · 14c.

Both tiers drawn per R22. Archetype: assistant-detail-tabs.md.

The three leftover honesty rules on one compact frame. Connect is finished (no Reconnect). Wallet is still loading. Brain has one Optional row — not a blocker. Header is quiet Continue to Try, never amber Complete Setup, never Activate.

Retreat Booking
Takes the booking, chases the deposit, keeps your roster true.
$0.35 per booking
Continue to Try ✕
Overview› Personalize › Connect› Try
01 · Connect apps — all connected
4 connected ✓ — show all⌄
02 · Wallet
Wallet balanceEach booking draws $0.35 from your prepaid balance …
03 · Brain Check
What you sell 1 of 2
✓Dates & capacity
Apr 12–19 · 12 spots
Edit in Brain →
○OfferingsOptional
Add packages later — it can take a booking without them
Add in Brain →
7 of 8 ready — it can take a booking · 1 to review
Try reads this same check back as one line — it never re-asks.
Ready to run Apps ✓ · Wallet · Brain ✓
Wallet pending — no first-paint ✕
  • Wallet paints the word only — no ✓, no amber ✕ — while usePaymentMethods / the first payment fetch is in flight. A first-paint Wallet ✕ is a FAIL only after the bar has settled (~1s). Does not rewire canProceed.
Attention ≠ cannot run
  • Offerings Optional is attention, not a blocker. Summary MUST read “it can take a booking · 1 to review” — never “before it can”. Footer Brain stays ✓ (ready: true). Contrast #sec-5, where Dates & capacity is a blocker and “before it can take a booking” is correct.
  • 2026-08-16 (AC-BRAINGATE-11): the row action tone follows the same gate-flag rule as its glyph — a recommended/optional row's "Add in Brain →" stays muted (bc-act, no amber class) even while its status glyph is dim ○; amber is reserved for a row the gate itself flags blocking (never re-derived from status alone — a required field the gate marks satisfied stays muted even if its display status is unverified). This frame previously rendered "Add in Brain →" amber on the Optional row, contradicting its own "not a blocker" note — fixed to match #sec-5.
Header — Continue to Try
  • Connect is done, canActivate is still false (Try not finished) → quiet Continue to Try. Amber Complete Setup is only for incomplete Connect/Personalize (or guests). Activate is white primary and only when canActivate. Full four-label set: explore.html #f9.

As a founder setting up Retreat Booking, the Brain Check says Prices is missing. I tap Add in Brain → and my actual playbook takes over the screen — the same book I read on Brain — with the Teach your Brain bar under it. I tap the bar, type my prices, tap Read, and I watch my chapter fill in. I hit Close and I'm back on the exact Connect step I left, with the row already re-read. No form I've never seen before, and nothing half-visible behind a column.

WALKTHROUGH — one door, the real page, FULL SCREEN (Peyton 2026-09-12: "takeover for now")

 1  Connect · 03 Brain Check   Prices ○ · "Add in Brain →"        (frame 5, unchanged)
 2  Book TAKES OVER the screen the REAL /brain/book, chapter 03    full-cover portal, z 10300
                               scaffold + "Teach your Brain ›" + the Teach bar docked
                               the Connect sheet stays mounted UNDERNEATH, never visible
 3  Tap the bar                the peek rises inside the takeover  no dim — the chapter stays readable
 4  Type · Read                the sheet takes the material        the peek never asks (v5.27)
 5  She SEES the chapter update her prices, in her own book        drafted — Save to Brain confirms
 6  Close                      back on the SAME Connect tab        the row has already re-read
 6a Closed before saving       row: Prices ⚠ · draft ready — Save to Brain   still the blocker; Brain ✕
 6b Closed after saving        row: Prices ✓ Confirmed · just now (frame 5's plain ✓ row)

 GEOMETRY, corrected 2026-09-12: this is NOT frame 14's 40/60 split. Production renders the
 Book as createPortal(<div class="ink-book fixed inset-0 bg-black">) — it covers the whole
 viewport. Same slide-over plumbing (PageSlideOver 'brain'), different geometry. Frame 14's
 Connects and funds destinations ARE real 60/40 page panes and keep the split.

 Retired FROM THIS DOOR (not deleted): the focusSection co-edit form. Accepted trade (Peyton
 2026-09-10): some setup-flow confusion, in exchange for removing the messy left co-edit
 panel from the assistant path.
(1) "Add in Brain →" tapped — the REAL Book takes over the WHOLE screen (Peyton 2026-09-12: takeover, not a split). Chapter 03 scaffold, Teach bar docked, its own Close. The Connect sheet stays mounted underneath and is never visible.
Close·Your playbookv3
03Assistant reads
What you sell

Your offers, prices, and what's included

Retreats, workshops or products — what it's called · what it costs · what's included
01an offeringits price
02an offeringits price
03an offeringits price

Nothing here yet — this is the shape it takes. Teach your Brain ›

Close takes you straight back to where you were — your setup is untouched

Teach your Brainadd · change · remove
(2) The bar tapped — the peek rises inside the takeover (no dim: the chapter above stays bright and scrollable), her prices typed, Read live. One surface, not two panels.
Close·Your playbookv3
03Assistant reads
What you sell

Your offers, prices, and what's included

Retreats, workshops or products — what it's called · what it costs · what's included
01an offeringits price
02an offeringits price
Teach your Brain✕
Bali Reset $1,950 · Lisbon Making Week $3,400 · private buyout $18,000 — a 30% deposit holds the seat
⤒ Drop a file, folder, or image⇄ Google
Read
(3) Read landed — she sees her chapter updated, in her own book, still in the takeover. The rows are a DRAFT until she saves (v5.27: Read never auto-confirms), so the chapter says so. This is the beat the split geometry used to hide behind a 40% column.
Close·Your playbookv3 · draft
03Assistant reads
What you sell

Your offers, prices, and what's included · 3 offerings

Bali Reset
$1,950
30% deposit holds the seat
Lisbon Making Week
$3,400
30% deposit holds the seat
Private buyout
$18,000
30% deposit holds the seat
Draft from what you just told us — Save to Brain to confirm
Save to Brain
Teach your Brainadd · change · remove
(4) Close — the takeover lifts and she lands on the SAME Connect tab she left, with the row already re-read. Closed BEFORE saving here, so the draft is still waiting and the row is still the blocker: Prices ⚠ · draft ready — Save to Brain. After Save to Brain it is frame 5's plain ✓ Confirmed row. Cropped to the module.
03 · Brain Check
What you sell 1 of 2
✓Dates & capacity
Apr 12–19 · 12 spots
Edit in Brain →
⚠Prices
Draft ready in your playbook — Save to Brain to confirm
Review in Brain →
How you run 2 of 3
✓Deposit terms
Confirmed
Edit in Brain →
○Cancellation windowOptional
Lets it answer “can I move my dates?” on its own
Add in Brain →
5 sections ready ✓show all
! 7 of 10 ready — Prices needs you before it can take a booking · 1 to review
Try reads this same check back as one line — it never re-asks.
Ready to run Apps ✓ · Wallet ✓ · Brain ✕
Acceptance
  • ↗ AC-BRAINGATE-09 — the row still names the chapter (What you sell → chapter 03); the pane opens the Book scrolled to that chapter.
  • ↗ AC-BRAINGATE-11 — glyph / action tone unchanged: a real blocker stays loud amber until the row re-reads; while the pane is open the row reads Adding….
  • NEW (PRD debt · #4714 item 6) — Add in Brain → / Edit in Brain → on the wizard and the assistant detail sheet open PageSlideOver on the REAL /brain/book (Teach bar included) — never <BrainPage focusSection>'s co-edit pane.
  • ↗ AC-BRAIN-213 — geometry corrected 2026-09-12 (Peyton: "takeover for now"). The Book renders as a full-cover portal (PlaybookBookPage → createPortal(<div class="ink-book fixed inset-0 flex flex-col bg-black">), z 10300 + zIndexOffset) — it covers the whole viewport, and the host sheet stays mounted underneath but is never visible. The earlier drawing of a left 40% pane with the assistant sheet beside it was wrong. The Book's own Close (or Esc, or the wizard's back chevron) closes the layer via onEmbeddedClose — never navigate('/brain').
  • NEW (PRD debt · #4714 item 6) — the peek rises inside the takeover and never asks; on close the Brain Check re-reads without a page reload, and she lands on the SAME tab she triggered from. Read never auto-confirms (v5.27 unchanged): the draft lands in the Book and Save to Brain confirms it; a row whose draft is unsaved stays a blocker and says so.
  • Tier: 1180 takeover drawn; 768–1023 and 375 are the same full-cover geometry (a takeover has no tier-dependent split to collapse — 375 drawn at 5d-m) — at 375 in wave 1 the bar opens the FULL sheet, not the peek.
Design notes
  • One Book, everywhere. The pane is the page she already knows — same paper, same scaffold, same bar — so "Add in Brain" stops meaning "a form we made for this step". The scaffold's own Teach your Brain › and the bar open the same peek.
  • The co-edit pane is retired from this door, not deleted. Frame 14 / 14b / 14d still draw focusSection's form for their own stories; nothing there is redrawn by this frame. If a later ruling retires it elsewhere, that is its own frame.
  • The draft-pending row is a NEW Brain Check state. BrainCheckStatus (useBrainReadiness.ts:109) has no draft member — ready · missing · thin · junk · stale · unverified — so "Draft ready in your playbook — Save to Brain to confirm" needs a status the readiness read can see (NEW, PRD debt · #4714). Glyph stays the blocker's ⚠, action is the existing degraded-state verb Review in Brain → (opens the Book at the draft). What the Book itself shows after Read is wave 2 (brain.html f-pb-peek-read).
  • Ink & Air on the pane: paper mixes only, no --fg-*; the bar's glass is the ink mix .06 + blur; nothing gold anywhere in this flow — the lantern stays with real blockers on the Connect side.

Both tiers drawn. Archetype: assistant-detail-tabs.md · Book frames: brain.html#f-pb-bar / #f-pb-peek.

Every Connect row is TWO controls with one job each. Badge = which apps are in play for the role (default seeded from Personalize/channel choices) — carries a ▾ only when ≥2 apps are actually in play. Status button = connection lifecycle only (Connect white/no-chevron → Connected ⌄ → Reconnect ⌄ → Pending ⌄); disconnect/reconnect/switch-account live in ITS menu. The two never conflate.

Pass 3 (2026-08-10) adds one rule that runs through every frame below: there is ONE control species, and an impossible action is greyed and explained — never removed. Wherever a connection's lifecycle is shown — the row, and every app inside an expanded picker — it is the same button with its chevron INSIDE it. The disambiguation list's old Connected ✓ text + underlined Disconnect link is deleted. A connected status button ALWAYS carries its chevron, and a menu item that can't fire (Disconnect on MystFlo AI, Reconnect while Pending, a row-level action on a multi-app row) renders greyed with its reason on the line beneath it. 375 first, then the 640 stack boundary, then desktop.

Why this does NOT reopen the badge-caret rule: the two controls are asked different questions. The badge answers “which app?” — with one app in play there is no list, so a caret would open onto nothing, and that affordance stays deleted (2026-08-09 stands). The status button answers “what can I do with this connection?” — and there is always an answer, including “not this one, and here's why.” The test: does opening it tell her something the collapsed state didn't? A one-app badge: no. A menu with a greyed, explained item: yes.

375 · collapsed — single-app side (Retreat Booking): only Storage earns a ▾
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌄
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
Payment Stripe
Takes the deposit for this booking
Connected ⌄
Alerts Slack
Pings you when a booking needs your call
Connected ⌄
Storage Google Sheets ▾
Where your bookings land
Connected ⌄

Read the two arrows separately. The badge ▾ appears once, on Storage (3 real destinations) — one app in play everywhere else, so no caret and no ⊘ coming soon row behind an empty arrow (the 2026-08-07 placeholder stays deleted). The status ⌄ appears on EVERY connected row including AI Model, because every connection has an answer to “what can I do here?” — even when the answer is “nothing, and here's why” (AI Model's menu, two frames down). Below 640px every row stacks the status button onto its own line — one rule, all rows (see the 640 pair below).

375 · collapsed — multi-app side (Waitlist + Launch): Communication runs TWO apps
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄

Two apps in play on one role — the badge NAMES both and earns its ▾ (several connected at once counts the same as real alternatives). The channel picks were made in Personalize; the badge default reads them back. No AI Model row — WAITL1 uses no AI (absence, not exception).

375 · expanded — Storage tapped (real picker, 3 destinations)
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌄
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
Payment Stripe
Takes the deposit for this booking
Connected ⌄
Storage Google Sheets ▴
Where your bookings land
Connected ⌄
MystFlo Storage
○Records list on Pulse
Bookings stay in this assistant's own records list
· Free
Google Sheet
◉Create a new one
We make a new sheet in your Drive with the template
· Free
○Link a sheet I already have
We add a new tab — we never touch your existing tabs
· Free
Your Supabase (spreadsheet only)
○Link your project · Free
⊘Create a new one coming soon · Free
375 · status menu, single-app row — the baseline: one live action
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌃
Disconnect
Switch account… shipped 2026-08-17

One app in play, so the target is unambiguous and Disconnect fires directly — no ellipsis, no which-app step. Two taps from collapsed to done. The standalone "Switch account" button (T1164) is retired into this menu; its Active-assistant muted/live behavior is shipped (frame 9d). .dim = muted-but-tappable (it opens an explainer), which is a different thing from .off = greyed-and-explained in the next two frames.

375 · AI Model — every item greyed, and the menu STILL opens pass 3 · Peyton's example
01 · Connect apps
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌃
Disconnect
MystFlo AI is built in — there's nothing to disconnect.
Switch account…
MystFlo AI is built in — there's nothing to switch.

This is the pass-3 rule at its hardest case. Nothing here can fire — and the control does NOT collapse to a bare "Connected" chip. The chevron stays, the menu opens, and it answers the question the founder actually had: can I turn this off? — no, and here's why. That is real content, not a stub. Contrast with the badge: a one-app badge caret would open onto a list that says nothing the collapsed badge didn't, which is why THAT affordance is still deleted. Build: this retires ConnectionStatusButton's hasAnyMenuAction fallback for role rows — see the build note at the foot of this section.

375 · MystFlo Storage — the SECOND row that shipped a dead chip pass 3 · copy signed 2026-08-10
01 · Connect apps
Storage MystFlo Storage
Where your bookings land — this assistant's records list on Pulse
Connected ⌃
Disconnect
MystFlo Storage is where your records live — there's nothing to disconnect.

AI Model was never the only case — this row is the other half of the same defect. The 2026-08-10 ruling names "Storage and AI Model", and this is Storage: MystfloStorageRow, the internal, zero-click destination. Structurally it IS the AI Model frame directly above — nothing external exists to disconnect, so its one item is .off and the menu still opens to say so. Note the badge carries no ▾: internal storage has no picker, so control 1 has nothing to open (2026-08-09 badge rule, untouched) while control 2 still answers what can I do here?. Drawing both Storage rows together is deliberate — fixing one and not the other is exactly how this shipped half-done the first time.

375 · Storage WITH a destination picker — same route as the multi-app row, different reason pass 3 · copy signed 2026-08-10
01 · Connect apps
Storage MystFlo Storage ▾
Where your bookings land — tap the badge to send them somewhere else
Connected ⌃
Disconnect
Pick a different destination in MystFlo Storage ▾ above.

Same badge word, one caret's difference, and a different reason entirely — that is why these two are drawn side by side. This is StorageRoleRow, which DOES own a picker (three destination groups), so "disconnect" isn't the verb that applies: the founder doesn't sever storage, she sends it somewhere else. The item greys and points at the badge — the same ROUTE as the multi-app row two frames down, reached by a different road. Read this against AC-EXPLORE-17b, not AC-EXPLORE-17: Storage is a pick-one-of-N role, so it is explicitly NOT the "≥2 apps running at once" ambiguity case and never says "N apps run here". It greys under AC-EXPLORE-21 (an item that cannot fire) — 17b's "keeps a LIVE row-level action" governs the ambiguity rule, and does not license a live Disconnect that has nothing to disconnect. Build: the badge name inside the reason is READ FROM THE ROW, never hardcoded — same derivation lesson as the multi-app count (#3310); a founder who has picked Google Sheets must read "Pick a different destination in Google Sheets ▾ above."

375 · Pending — Reconnect greyed, Disconnect live pass 3
01 · Connect apps
Payment Stripe
Takes the deposit for this booking
Waiting on Stripe to finish verifying your account
Pending ⌃
Reconnect
Stripe is still verifying your account — there's nothing to fix on your side yet.
Disconnect

Pending used to simply OMIT Reconnect — correct behavior, invisible reasoning. Greyed-and-explained keeps the menu's shape identical across all four states, so the founder learns one menu instead of four, and the verb ledger stays honest: Pending means we're waiting on the provider, so Reconnect genuinely cannot help. Disconnect stays live — walking away is always hers.

375 · multi-app row — the row-level actions are greyed, and say where to go pass 3 · replaces the which-app MODE
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Connected ⌃
Disconnect
Two apps run here — open WhatsApp + Resend ▾ above and disconnect the one you mean.
Switch account
Same reason — pick the app first.

The correctness rule is unchanged: an action never fires against an unnamed app. What changes is how that's expressed. Pass 2 routed it as a hand-off — Disconnect… put the BADGE into a "which app?" mode. Pass 3 states it plainly instead: a row-level disconnect is one of the things that isn't possible here, so it takes the same greyed-and-explained treatment as MystFlo AI, and the founder is sent to the badge — which was always the control that answers "which app?". The two controls now never touch. Three taps to act (badge ▾ → that app's Connected ⌄ → Disconnect), one species the whole way.

375 · multi-app badge expanded — each app carries the SAME button+chevron
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Connected ⌄
Communication — 2 apps
◉WhatsApp Business
The launch message in WhatsApp
Connected ⌄
◉Resend
The launch email
Connected ⌄
⊘Gmail coming soon

This frame replaces the old “DISCONNECT WHICH APP?” list. Gone: the Connected ✓ green text and the underlined Disconnect link — two elements, neither of them a button, doing control 2's job in a second species. Each app now carries the identical status button, one tier down (.mini: 10.5px, same pill, chevron inside), and its menu is the same menu — Disconnect, Reconnect, Switch account, greyed-and-explained where they don't apply. The list has one title, not two: it is always “which apps are in play”, never re-titled by whatever the founder was trying to do.

375 · one app's menu, opened inside the picker — the same menu, one tier down
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Connected ⌄
Communication — 2 apps
◉WhatsApp Business Connected ⌄
◉Resend Connected ⌃
Disconnect Resend
Switch account… shipped 2026-08-17

Down here the app IS named, so the action is live and the label says the target out loud — “Disconnect Resend”, never a bare “Disconnect” that the founder has to trust. WhatsApp is untouched and keeps sending. This is the tap that the greyed row-level item pointed her to.

375 · expired token on a multi-app row — collapsed names THE app
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend's connection expired — sign in again to keep launch emails going out
Reconnect ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄

Never a bare row-level "Reconnect" when two apps run: the status line NAMES the broken app while still collapsed (B2's reserved slot — the descriptive line stays put). WhatsApp is untouched and keeps sending.

375 · expired, expanded — per-app health, repair lands on Resend only
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Resend's connection expired — sign in again to keep launch emails going out
Reconnect ⌄
Communication — 2 apps
◉WhatsApp Business
The launch message in WhatsApp
Connected ⌄
◉Resend
The launch email
Reconnect ⌄

Expanded, each app carries its OWN status button — and health is carried by the button's own label + colour (Reconnect, amber), which is exactly how the row-level button carries it. No separate Expired chip beside a link: one control per app, saying its state and holding its actions. Reconnecting never touches WhatsApp.

375 · picked-but-not-connected — a white Connect surfaces shipped
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Resend isn't connected yet — connect it to send launch emails
Connect
WhatsApp
◉WhatsApp Business Connected ⌄
Email
◉Resend
Sends the launch email from your address
Connect
⊘Gmail coming soon

Picking an app that isn't connected surfaces Connect — white, and the one legitimate no-chevron state: there is no connection yet, so control 2 has no lifecycle to hold and the button IS the action. That is not the collapsed-affordance defect pass 3 bans — it's the difference between “this control has more to say” (chevron) and “this control does one thing” (no chevron). Tapping it opens the LEFT co-edit slide sheet (next frame), never a nested modal. The ⊘ Gmail row is legal HERE — inside a multi-app picker it's a real roadmap alternative among ≥2 live groups, not a placeholder propping up an empty caret.

375 · Connect tapped — the Connects page slides in as the REAL page shipped
Connects · Email
Resend

Sends your launch emails from your own address.

API key * required
Paste your Resend API key…
Connect Resend

◄ tap the peek edge to go back — your setup is untouched

SETUP — TAP TO RETURN
600 · below the 640 boundary — EVERY row stacks (one rule, decided this pass)
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Connected ⌄
Alerts Slack
Pings you when a signup needs your call
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄

Stack-rule decision (this pass): one structural boundary at sm 640px for ALL Connect rows — below it every status button drops to its own line, above it every row is inline. Pass 1 mixed the two (Communication stacked at ~600 while Alerts/Storage stayed inline because their content happened to fit) — content-driven per-row reflow is exactly what canon U8 bans: structure changes at NAMED breakpoints, nowhere else. A list where sibling rows disagree reads as two different row types.

768 · at/above the boundary — every row inline, statuses align in one column
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend's connection expired — sign in again to keep launch emails going out
Reconnect ⌄
Alerts Slack
Pings you when a signup needs your call
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄

Inline tier of the same three rows, one carrying the expired state — the named-app status line sits in B2's reserved slot, so row height never jumps and the status column stays aligned.

768 · both controls open at once, mid-tier — greyed row menu + live per-app buttons
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Connected ⌃
Disconnect
Two apps run here — pick one below.
Switch account
Same reason — pick the app first.
Communication — 2 apps
◉WhatsApp Business Connected ⌄
◉Resend Connected ⌄

Both controls drawn open together so the relationship reads at mid-tier: the row menu anchors under its own trigger and says what it CAN'T do plus where to go; the badge's list expands in the row's own space and carries the live buttons. The reason line renders here identically to 375 — it is not a hover tooltip, so nothing about it is desktop-only.

560 · the two controls, named
The anatomy
1Label — the role
"Communication" / "Storage" — never changes, never becomes the app's name
2Badge — WHICH apps are in play
Default seeded from the founder's Personalize/channel choices. ▾ only when ≥2 apps are actually in play (real alternatives, or several connected at once). One app = no caret, no coming-soon stub.
3Status button — connection lifecycle ONLY, one species everywhere
Connect (white, no chevron — the button IS the action) → Connected ⌄ → Reconnect ⌄ → Pending ⌄ (T336 five-state contract). Chevron INSIDE the pill, never a caret parked beside it. The identical control renders one tier down (.mini) for every app inside an expanded picker. Its menu holds Disconnect / Reconnect / Switch account (T1164 retired into it; Active-muted behavior shipped 2026-08-17).
4Impossible ⇒ greyed + explained, never removed
A connected status button ALWAYS opens. An item that can't fire renders .off (--fg-30, cursor:not-allowed, aria-disabled, no red on a dead Disconnect) with its reason on an always-visible line underneath — never a hover tooltip. Three live cases: MystFlo AI (product gate) · Reconnect while Pending (waiting on the provider) · any row-level action on a multi-app row (no named target).
5Disambiguation — the badge owns “which app”, always
≥2 connected apps: the row-level action greys out and points at the badge; the badge's list carries a live per-app status button each. An expired token also names its app in the collapsed status line. The action can never fire against an unnamed app — and the picker is never re-titled into a “which app?” mode by control 2.
6Connect — the left co-edit slide sheet
A picked-but-unconnected app surfaces white Connect → PageSlideOver slides the real Connects page in from the LEFT (R35 mechanic, frame 14) — never a nested modal. Shipped.
desktop 1180 · frame 5 one tap later — Storage badge tapped, picker opens in the row's own space B9
Retreat Booking
Takes the booking, chases the deposit, keeps your roster true.
$0.35 per booking
✕
Overview› Personalize › Connect› Try
01 · Connect apps — one list of everything it talks to · 2 need you
Communication WhatsApp Business
Where your guests already message you
Your WhatsApp connection expired — sign in again to continue
Reconnect ⌄
Payment Stripe
Takes the deposit and the balance for this booking
Waiting on Stripe to finish verifying your account
Pending ⌄
Storage MystFlo Storage ▴
Where your bookings land — this assistant's records list on Pulse. Tap the badge to send them somewhere else.
Connected ⌄
MystFlo Storage
◉Records list on Pulse
Bookings stay in this assistant's own records list — nothing external to connect
· Free
Google Sheet
○Create a new one
We make a new sheet in your Drive with the template
· Free
○Link a sheet I already have
We add a new tab — we never touch your existing tabs
· Free
Your Supabase (spreadsheet only)
○Link your project · Free
⊘Create a new one coming soon · Free
7 connected ✓ — show all⌄
02 · Wallet
Wallet balanceEach booking draws $0.35 from your prepaid balance $41.20 →
03 · Brain Check
6 of 8 ready — unchanged from frame 5show all
The rail doesn't react to the picker — one job, one surface.
desktop 1180 · multi-app side (Waitlist + Launch) — collapsed, Resend expired, the row NAMES it
Waitlist + Launch
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run
✕
Overview› Personalize › Connect› Try
01 · Connect apps — one list of everything it talks to · 1 needs you
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend's connection expired — sign in again to keep launch emails going out
Reconnect ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄
02 · Wallet
Wallet balanceEach run draws $0.25 from your prepaid balance $41.20 →
03 · Brain Check
5 of 5 ready ✓show all
5 of 5 ready — it can open your waitlist
Try reads this same check back as one line — it never re-asks.
desktop 1180 · one tap later — the row menu greys out and points at the badge; each app carries its own status button pass 3
Waitlist + Launch
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run
✕
Overview› Personalize › Connect› Try
01 · Connect apps
Communication WhatsApp + Resend ▴
The launch goes out on WhatsApp and email
Connected ⌃
Disconnect
Two apps run here — open WhatsApp + Resend ▾ and disconnect the one you mean.
Switch account
Same reason — pick the app first.
Communication — 2 apps
◉WhatsApp Business
The launch message in WhatsApp
Connected ⌄
◉Resend
The launch email
Connected ⌄
⊘Gmail coming soon
Storage Google Sheets ▾
Where your signups land
Connected ⌄
03 · Brain Check
5 of 5 ready ✓ — unchangedshow all
The rail doesn't react to the menu or the picker — one job, one surface.
desktop 1180 · Connect tapped on unconnected Resend — Connects page slides in from the LEFT (R35 mechanic) shipped
Connects · Email
Resend

Sends your launch emails from your own address.

API key * required
Paste your Resend API key…
Connect Resend

◄ tap the peek edge to go back — your setup is untouched

Waitlist + Launch
Connect · 01 Connect apps
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend is being connected on the left — this row updates the moment it's done
Connecting…
Storage Google Sheets ▾
Where your signups land
Connected ⌄
Story
  • At 11pm on her phone, a founder whose launch email bounced sees WHICH app broke without expanding anything, fixes exactly that one, and never loses WhatsApp while she does it.
  • The same founder taps the arrow on MystFlo AI wondering if she's paying for something she can switch off. She gets a straight answer in one tap — “MystFlo AI is built in — there's nothing to disconnect” / “there's nothing to switch” — instead of an arrow that isn't there and a question she carries around all night.
  • She tries the same tap on Storage — and gets an answer there too, a different one depending on which Storage row she's on: nothing to disconnect (her records live on MystFlo), or “pick a different destination in the badge above.” One gesture, always answered, never a dead chip that makes her wonder whether she tapped it wrong.
Acceptance Peyton rulings 2026-08-09 + 2026-08-10 — kit design-decisions.md
  • Badge caret appears ONLY when ≥2 apps are actually in play for the role (real alternatives, or several connected at once); single-app rows carry no caret and NO ⊘ coming soon placeholder. Unchanged by pass 3 — AC-CONN3-01 ↗ (§ Connect apps rule 7/7a).
  • Status button follows the T336 five-state contract — Connect white/no-chevron · Connected ⌄ · Reconnect ⌄ · Pending ⌄ — and its menu is the ONLY home for Disconnect / Reconnect / Switch account (T1164 standalone button retired) — AC-CONN3-01 ↗ · AC-EXPLORE-18 ↗.
  • Every connected status button carries its chevron and opens a menu — including when no item can fire. hasAnyMenuAction's static role="status" chip is retired for role-mode rows; interactive={false} (the picker-modal categories) is untouched — NEW (PRD debt · pass 3).
  • An item whose action isn't possible renders greyed with an always-visible reason line, never removed and never a hover tooltip: Disconnect on ai_model (“MystFlo AI is built in — there's nothing to disconnect.”) · Switch account… (“MystFlo AI is built in — there's nothing to switch.”) · Reconnect while Pending · any row-level action on a ≥2-app role — NEW (PRD debt · pass 3).
  • BOTH Storage rows carry the chevron and the explained Disconnect — the ruling names “Storage and AI Model”, and Storage is two components, not one. MystfloStorageRow (internal, no picker, no badge caret): “MystFlo Storage is where your records live — there's nothing to disconnect.” StorageRoleRow (owns the 3-group destination picker, badge caret present): “Pick a different destination in {badge} ▾ above.” — badge name DERIVED from the row, never hardcoded (#3310 lesson) — AC-EXPLORE-20 ↗ · AC-EXPLORE-21 ↗.
  • Storage is NOT the multi-app ambiguity case and must never say “N apps run here”. It is pick-one-of-N (AC-EXPLORE-17b ↗), explicitly carved out of AC-EXPLORE-17 ↗. Its greying is governed by AC-EXPLORE-21 ↗ alone — 17b's “keeps a LIVE row-level action” scopes the ambiguity rule and does not require a live Disconnect on a row that has nothing to disconnect.
  • Every app inside an expanded picker carries a full ConnectionStatusButton (.mini tier), showing that app's own state and holding that app's own menu; the Connected ✓ text + underlined Disconnect link pair is deleted. Health is still three-state — a never-connected or just-disconnected app reads Connect, never “Connected ✓” — AC-EXPLORE-17 ↗ (control species is NEW (PRD debt · pass 3)).
  • On a role with ≥2 connected apps the action still can never fire against an unnamed app; an expired token names its app in the collapsed status line, never a bare row-level “Reconnect” — AC-CONN3-03 ↗ (the ROUTE changes: greyed row item pointing at the badge, replacing the pass-2 Disconnect… → which-app mode — NEW (PRD debt · pass 3)).
  • The `ai_model` role renders via the shared AiModelPicker, badge "MystFlo AI", status "Connected", no badge caret — AC-EXPLORE-08 ↗.
  • One stack boundary at sm 640px for every Connect row — AC-CONN3-04 ↗.
  • Picking an app that isn't connected surfaces white Connect, which opens the LEFT co-edit slide sheet (R35 / PageSlideOver, frame 14's mechanic) — never a nested modal — shipped.
Design notes
  • Two controls, two territories, and after pass 3 they no longer touch. The status menu anchors under the status button; the picker expands under the badge in the row's own space (hairline groups, never a nested modal). Pass 2's one hand-off — a status-menu action re-titling the badge's list into “which app?” mode — is gone: the badge's list has exactly one title and one job, and the row-level action simply greys out and names where to go.
  • Why the always-open status menu doesn't reopen the badge-caret question. The two arrows answer different questions, so “is there something to show?” resolves differently. Badge = which app? — one app in play means the expanded list would restate the collapsed badge, so the caret stays deleted (2026-08-09 intact). Status = what can I do here? — always answerable, including “nothing, because X.” The operative test for any future control: does opening it tell her something the collapsed state didn't?
  • A greyed-and-explained item is NOT the retired ⊘ … coming soon stub. The stub announced an unbuilt FEATURE to justify an otherwise-empty arrow. A greyed item explains, in the present tense, why an action this control genuinely owns everywhere else doesn't apply HERE. Rule of thumb: legal when the item names an action the control already owns elsewhere; illegal when it names a feature that doesn't exist yet. ⊘ Gmail · coming soon inside a ≥2-group picker stays legal on its own separate grounds (a real alternative among real ones).
  • No tooltips — the reason is an inline line, at every tier. A hover tooltip is invisible on touch, and a disabled menu item can't reliably take keyboard focus either, so the hover/focus path fails twice over. Long-press is undiscoverable and collides with iOS selection. The reason is one short sentence: it costs a line and buys a founder who never has to guess. It renders identically at 375, 768 and desktop — a reason only desktop users can read is a reason the phone user doesn't have. Reuses the shipped .smenu-note vocabulary as .smenu-why, not a new overlay species (a tooltip over a menu is a second overlay on one job).
  • Two muted flavours, deliberately different. .off = cannot act, reason inline, aria-disabled, cursor:not-allowed. .dim = muted but tappable, opens an explainer WITH actions (9d's Switch-account-while-Active .notice + “Pause to switch” / “Start a new instance →”). The dividing line: if the reason comes with a path forward the founder can take right now, it earns the notice panel; if it's purely informational, it's an inline line.
  • A disabled Disconnect is never red. Red marks a live destructive action; greyed red reads as a broken button. .off drops to --fg-30 flat.
  • Touch targets survive the .mini tier. The per-app button renders 10.5px/3px-9px visually but keeps the 44×44 hit area the row-level button already carries below sm (min-h-[44px] sm:min-h-0 in ConnectionStatusButton) — visual density is not hit density.
  • The Storage expansion stays VERBATIM from DestinationPicker.tsx (2026-05-22 Template-first lock; the ① MystFlo Storage group remains the one honest drawn delta, #3251) — if copy reads awkwardly the fix is a component change, not a mockup rewrite.
  • Stack rule, decided this pass: ONE structural boundary at sm 640px for every Connect row — below it every status button drops to its own line, above it every row is inline. Canon U8: structure changes at named breakpoints only; pass-1's content-driven mix (Communication stacked at ~600 while Alerts/Storage stayed inline) is the defect this retires. AppRow.tsx's deliberate inline-at-all-widths cluster is knowingly reversed for the status control.
  • Where ⊘ coming soon still lives: only INSIDE a picker that already has ≥2 live groups (Gmail under Email; Supabase's create-new) — a roadmap alternative among real ones, never a stub propping up an otherwise-empty caret. AI Model stays caret-free permanently (#4959) — BYOK is deleted, not a second provider waiting to grant a caret.
Supersessions + build state honest ledger
  • Supersedes (2026-08-10, pass 3): ① this section's own plain-text disambiguation rows — .app-st "Connected ✓" + underlined .app-act "Disconnect" — DELETED and redrawn as per-app status buttons (those frames are replaced, not kept alongside); with them goes the C2-derived neutral-underline treatment for in-picker actions, which existed only to serve that shape. ② ConnectionStatusButton's hasAnyMenuAction fallback for role rows — the static role="status" chip with no chevron, which is exactly why Storage and AI Model render a bare "Connected" today. ③ Pass 2's Disconnect… / Reconnect… ellipsis labels and the which-app MODE they opened.
  • Supersedes (2026-08-09, still in force): the 2026-08-07 "caret is structural on every row except AI Model" amendment and its (current) + coming soon single-provider expand (that frame is deleted, not redrawn). Also still in force from 2026-08-04/05/06/07: label/badge split · one Storage row, three destinations · verbatim picker copy · one list, no tiers · decision-in-Personalize, connection-in-Connect (the badge default reads those picks back).
  • NOT superseded — read this before "fixing" one control to match the other: the badge-caret rule is untouched by pass 3. Control 1 still carries a caret only at ≥2 apps, with no ⊘ coming soon stub behind an empty one. Pass 3 governs control 2 only. The two rules disagree on the surface and agree underneath: show an affordance when opening it says something new.
  • Build state: PR #3281 shipped the pass-1 shell under the OLDEST rule — AppRow/RoleRow COMING_SOON_COPY shells and structural carets must be REMOVED. PR #3288 shipped pass 2's two-control split. Pass 3 adds: always-open status menu (retire the hasAnyMenuAction fallback for role rows; KEEP the interactive={false} branch for the picker-modal categories), .off disabled items + inline reason lines, per-app .mini status buttons inside pickers, the greyed row-level action on multi-app rows, and — added 2026-08-10 after design review caught it half-delivered — the explained Disconnect on BOTH Storage rows (MystfloStorageRow internal · StorageRoleRow picker-owning), which the ruling named alongside AI Model from the start. Pass 2 leftovers still open: multi-app badge + aggregated status, expired-names-the-app status line. Connect → slide sheet and Switch-account muted/live shipped 2026-08-17.
  • Stretch-bug guard (kit design-lessons.md flex-col-row-container-stretches-bare-children): the new .mini button lands inside .pick-row, and the <sm stack rule puts flex-col on row containers. Wrap it — <div className="flex-shrink-0"><ConnectionStatusButton …/></div> — and audit EVERY direct child of any container that gains flex-col, in both render trees, before calling this shipped.

Components: ConnectionStatusButton.tsx (T336 five-state, built — gains always-open menu, .off items, Switch account) · ChannelGroupRow.tsx BroadcastPickRow (carries the per-app .mini control; DisambiguateAppRow is the RETIRED pass-2 shape — do not rebuild it) · DestinationPicker.tsx (built, ① MystFlo Storage group shipped #3251) · AiModelPicker.tsx (no badge caret — product gate; gains the explained Disconnect) · MystfloStorageRow.tsx + StorageRoleRow.tsx (the two Storage rows — both gain the chevron + their own explained Disconnect; their file comments still describe the retired chevron-less fallback as correct and need rewriting with the fix). Contract: prd-pl-activation-wizard.md § Connect apps (rules 7a/9a CORRECTED to this pass in PR #3308, merged 2026-08-10 — plus AC-EXPLORE-20/21 minted and AC-EXPLORE-17 rewritten). Kit: design-decisions.md 2026-08-09 + 2026-08-10.

desktop 1180 · CHAT type — seated sheet, read-back left / trying-it right
On-Brand Support
Answers guest questions in WhatsApp from your Brain — and hands you the rest.
$0.50 per session
✕
Overview› Personalize › Connect › Try
What you're activating
Greeting“Hey! You've reached Salt & Stone — how can we help?”
Answershours · prices · availability
Routes to yourefunds, anything it can't ground
AppsWhatsApp Business · MystFlo AI
Brain✓ 7 of 7 ready — Your business · Branding · Questions and policies
Wallet$41.20 · $0.50 per session
Trying it
Replies are triggered by real customer messages Message your WhatsApp after activation to see it live. There's no way to fake a guest message before then — so we don't pretend to.
Send yourself the first one Right after you activate, open WhatsApp and message your own business number.
Name this one
Autumn retreat support
Activate — $0.50 per session

Pause anytime.

desktop 1180 · TESTABLE type (WAITL1) — same shell, test block replaces the notice
Waitlist + Launch
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run
✕
Overview› Personalize › Connect › Try
What you're activating
Headline“Join the October cohort waitlist”
Signups go toOctober cohort · Google Sheets
Launch blastWhatsApp, when you say go
AppsGoogle Sheets · WhatsApp · Email
Brain✓ 6 of 6 ready
Wallet$41.20 · $0.25 per run
Your launch message goes to WhatsApp for approval WhatsApp reviews every message sent to a list. Often minutes, sometimes hours, and it can take up to a day. It goes live automatically the moment they approve — you don't have to check back. Signups keep working the whole time.
Try it for real
Run one real signup

A test row on your sheet + the confirmation on your own WhatsApp. Free.

Run the test
Row added to “October cohort”
You (test) · joined 22 Jul · position 1
Confirmation sent to your WhatsApp
You're on the list for October — we'll message you the moment dates open.
Name this one
October cohort waitlist
Activate — $0.25 per run
R11 — Honest test, no fake capability
  • No pre-activation test run exists for WhatsApp chat types (9P3X/WACO01/WABOOK/COHB01) — replies only trigger on real inbound messages. Honest copy: “Replies are triggered by real customer messages — message your WhatsApp after activation to see it live,” plus a first-message nudge.
  • Testable per the CTO matrix: WAITL1 (real Sheet row + WhatsApp confirm) · BRVX01 (free sample draft) · doc/table types with a `webhook_url` (real n8n preview, `is_preview:true`). No `webhook_url` = no test, tab says so plainly — never a disabled button with no explanation.
  • Same fix applies in `on-brand-support.html` frame 5.
Provider window
  • Open-ended, never an ETA — “often minutes, sometimes hours, up to a day.” No countdown, no progress bar. COHB01/WSBK01 submit templates after activation, never drawn pending.
Structure + B7
  • Top: launch read-back (Personalize summary, apps, Brain state, wallet + price). Middle: test block by type. Bottom: name-this-instance + Activate.
  • Name field is the founder's only pre-activation naming moment (the other is the R17 rename pencil, post-activation).
  • B7: read-back is derived state, recomputed on every tab entry — no cached copy.

Both tiers drawn per R22. A real pre-activation chat sandbox is a deferred post-launch decision (ledger).

768 not yet drawn for this flow. Desktop and 375 are the contract.
§2 · Set up
3Pre detail sheet — Overview tab · 375 bottom sheet + desktop seated sheet — mobile
dimmed Explore peeks — tap to return
On-Brand Support
Answers guest questions in WhatsApp from your Brain — and hands you the rest.
✕
$0.50 per session
Overview Personalize Connect Try
What it does

It reads your Brain — prices, policies, hours, FAQs, and your brand voice — and answers guests in the voice you confirmed. Anything it can't ground in your knowledge gets handed to you.

How it works
01
Customer
“do you have space in September?”Any hour — 11pm included.
02
Brain ✦
Grounds the answer in your facts ✦ AIYour real prices and policies — never invented.
03
Assistant
Replies in your voice, in the same thread
tricky ones → routed to you
◎
Outcome
Guest helped, in your voiceYou never typed a word.
Key benefits
Answers while you sleep
Instant replies at the moment guests are deciding.
Sounds like you — because you confirmed it does
Your voice and policies, confirmed by you.
Story · acceptance · design notes — shared with the desktop half: frame 3 ↑ (one note, both tiers).
4ePersonalize — mobile 375 preview pattern (D2 locked) · tablet 768
Slide-up on demand — D2 locked · closed
Overview Personalize Connect Try
Handling rules
hours ✕prices ✕+ add topic
Greeting
Hey! You've reached Salt & Stone — how can we help?

Brain readiness lives on Connect →.

·· preview ··
Variant A · open — bottom-sheet preview
form dims behind — tap ✕ or drag down to return
✕
Hey! You've reached Salt & Stone — how can we help?
do you have space in September?
Real replies after activation
·· preview ··
Overview› Personalize› Connect› Try
Handling rules
hours ✕prices ✕+ add topic
Greeting
Hey! You've reached Salt & Stone…
Hey! You've reached Salt & Stone…
Real replies after activation
·· preview ··

tablet 768 — progressive: split engages where width allows, else the mobile pattern holds

R9 · D2 · C1 LOCKED 2026-07-23
  • Variant A (slide-up on demand) is the ONLY pattern — Variant B removed from file and ledger.
  • Form keeps full working height; a persistent “·· preview ··” pill bar docks above the fold; tap slides the preview up as a bottom sheet.
R23 — Build
  • Pill bar respects keyboard inset AND safe-area insets — never behind the keyboard, never under the home indicator.
  • 768 tablet stays progressive: split engages early at reduced width where it fits, else keeps the mobile pattern — never a squeezed two-column layout. Applies to every sheet frame in this file.
5Connect tab — apps · wallet · Brain Check — mobile R7 + R10
375 · ready to continue
dimmed Explore peeks — tap to return
Overview Personalize Connect Try
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌄
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
02 · Wallet
Wallet balanceEach session draws $0.50 from your prepaid balance $41.20 →
03 · Brain Check
Your business
✓Business description
Confirmed
Edit in Brain →
Where to find you
✓Hours
Ready
Edit in Brain →
✓Contact
Ready
Edit in Brain →
Questions and policies
✓Questions · 14 items
Confirmed
Edit in Brain →
Branding
✓Brand voice
Confirmed Jul 20
Edit in Brain →
How you run
✓Policies
Confirmed
Edit in Brain →
7 of 7 ready — it can answer guests
Connect and Try read this same check — you'll never be asked twice.
Continue to Try
375 · blocked — an app AND a Brain section need you
dimmed Explore peeks — tap to return
Overview Personalize Connect Try
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Your WhatsApp connection expired — sign in again to continue
Reconnect ⌄
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
02 · Wallet
Wallet balanceEach session draws $0.50 from your prepaid balance $0.00 →
Wallet empty — top up to keep runningAdd credit before you activate; nothing is charged until a run happens.
03 · Brain Check
Questions and policies
✓Questions · 14 items
Confirmed
Edit in Brain →
Branding 0 of 1
⚠Brand voice
Needs review — last confirmed Jun 12
Review in Brain →
How you run 0 of 1
○Policies
Add your refund & deposit policies — it can't answer these without them
Add in Brain →
4 sections ready ✓show all
5 of 7 ready — 2 need you before it answers guests
Connect and Try read this same check — you'll never be asked twice.
Continue to Try

Reconnect WhatsApp and add your policies to continue.

Story · acceptance · design notes — shared with the desktop half: frame 5 ↑ (one note, both tiers).
5dBrain Check row → the REAL Book with the Teach bar → full sheet (wave 1) → row re-reads — mobile NEW · #4714 wave 1 · 2026-09-10 view at desktop ↑↓
375 · (1) the Book, stacked over the sheet
Close·Your playbookv3
03Assistant reads
What you sell

Your offers, prices, and what's included

Retreats, workshops or products — what it's called · what it costs · what's included
01an offeringits price
02an offeringits price
03an offeringits price

Nothing here yet — this is the shape it takes. Teach your Brain ›

Teach your Brainadd · change · remove
375 · (2) the bar tapped — the FULL Teach sheet (wave 1)
Close·Your playbook
03Assistant reads
What you sell

Your offers, prices, and what's included

Teach your Brain✕

Your business — what you do and sell. A price change or a policy update.

What you can share
Your Instagram profilefull page, logged-in
A PDFprice list, menu, flyer
A Google Docconnect and link
Bali Reset $1,950 · Lisbon Making Week $3,400 · private buyout $18,000 — a 30% deposit holds the seat
⤒ Drop a file, folder, or image⇄ Google
Read
375 · (3) back on Connect before saving — draft ready, still the blocker
dimmed Explore peeks — tap to return
Overview Personalize Connect Try
03 · Brain Check
What you sell 1 of 2
✓Dates & capacity
Apr 12–19 · 12 spots
Edit in Brain →
⚠Prices
Draft ready in your playbook — Save to Brain to confirm
Review in Brain →
How you run 2 of 3
✓Deposit terms
Confirmed
Edit in Brain →
○Cancellation windowOptional
Lets it answer “can I move my dates?” on its own
Add in Brain →
! 7 of 10 ready — Prices needs you before it can take a booking · 1 to review
Ready to run Apps ✓·Wallet ✓·Brain ✕
  • 375 is the same full-cover takeover as desktop, not a tier collapse (amended 2026-09-12): the Book covers the screen at every width, and the Book's own Close (or Esc, or the wizard's back chevron) closes the layer and lands her back on the SAME Connect tab with the row already re-read. The bar is label-only at this width, 16px + safe-area off the foot.
  • Wave 1 at 375 opens the FULL Teach sheet (the 1.3-share-m chrome — brain.html#f-pb-peek-m-wave1) — the pinned peek is week 2. Title Teach your Brain per AC-BRAIN-126 — the bar and the sheet share the one string.
  • Story · acceptance · notes shared with frame 5d ↑ (one note, both tiers).
6Try tab — launch read-back + the test that actually exists — mobile R11 · CTO matrix binding
375 · CHAT type (9P3X / WACO01 / WABOOK / COHB01) — no test button
dimmed Explore peeks — tap to return
Overview Personalize Connect Try
What you're activating
Greeting“Hey! You've reached Salt & Stone — how can we help?”
Answershours · prices · availability
Routes to yourefunds, anything it can't ground
AppsWhatsApp Business · MystFlo AI
Brain✓ 7 of 7 ready
Wallet$41.20 · $0.50 per session
Trying it
Replies are triggered by real customer messages Message your WhatsApp after activation to see it live. There's no way to fake a guest message before then — so we don't pretend to.
Send yourself the first one Right after you activate, open WhatsApp and message your own business number. You'll see the real reply, from your real Brain, in seconds.
Name this one
Autumn retreat support

Your word for this instance — you can rename it anytime from its Details header.

Activate — $0.50 per session

Runs on your WhatsApp from the moment you activate. Pause anytime.

375 · TESTABLE type (WAITL1) — real test run + Meta notice
dimmed Explore peeks — tap to return
Overview Personalize Connect Try
What you're activating
Headline“Join the October cohort waitlist”
Signups go toOctober cohort · Google Sheets
AppsGoogle Sheets · WhatsApp · Email
Brain✓ 6 of 6 ready
Wallet$41.20 · $0.25 per run
Try it for real
Run one real signup

We'll add a test row to your sheet and send the confirmation to your own WhatsApp — so you see exactly what a guest sees. Free.

Run the test
Row added to “October cohort”
You (test) · joined 22 Jul · position 1
Confirmation sent to your WhatsApp
You're on the list for October — we'll message you the moment dates open. — Salt & Stone
✓ Real sheet, real message — the test row is yours to delete
Your launch message goes to WhatsApp for approval WhatsApp reviews every message sent to a list. Often minutes, sometimes hours, and it can take up to a day. It goes live automatically the moment they approve — you don't have to check back.
Name this one
October cohort waitlist
Activate — $0.25 per run
Story · acceptance · design notes — shared with the desktop half: frame 6 ↑ (one note, both tiers).
Activate
desktop 1180 · (a) activating, then (c) the partially-active landing — same seated sheet
Activating “October cohort waitlist”

About 20 seconds. Stay on this screen.

✓Checking your setup
✓Confirming billing & terms
✓Setting up your assistant
◍Running a live test~15s
Going live
…and where it lands

outcome (c) — partially active

Live for signups — launch message with WhatsApp Often minutes, sometimes hours, can take up to a day. It goes live automatically.
Working nowsignup page · confirmations
Waitinglaunch blast only
Open the signup pageSee it in Pulse
R12 — Five outcomes
  • Loader = C2 grouping of the real pipeline (auth → apps → BYOK-AI gate → payment → terms → workspace → test run → finalize), collapsed to: Checking your setup → Confirming billing & terms → Setting up your assistant → Running a live test → Going live.
(b) Failed · B6
  • Live-test failure = FULL rollback, nothing created/charged — say so in plain words. Retry + a named first fix.
  • “Message us” is a real link (`wa.me/<MYSTFLO_SUPPORT_NUMBER>`, config value, never hardcoded), run reference prefilled.
(c) Launch-pending
  • Drawn PARTIALLY ACTIVE, not Pending — `pending_template_approval` means replies/signups are already live, only the launch blast waits.
  • Active badge + amber meta line; flips on Meta's webhook, no polling, window open-ended (never an ETA).
  • COHB01/WSBK01 never drawn pending — they go active immediately, only chase/reminder sends wait.
(e) Template rejected · D3
  • Real state, red-family badge, named fix path (rewrite or pre-approved wording) — never a dead end.
  • Red reserved for true errors/terminal failures — a top-up-fixable state never earns red.

Both tiers drawn per R22; Pulse card twins for (c)/(e) above. Archetype: pulse-surface.md.

768 not yet drawn for this flow. Desktop and 375 are the contract.
§3 · Activate
7Activation — the five outcomes the real pipeline produces — mobile R12 · C2 pipeline
(a) Activating — 5 grouped steps
Activating “Autumn retreat support”

About 20 seconds. Stay on this screen.

✓Checking your setup
✓Confirming billing & terms
✓Setting up your assistant
◍Running a live test~15s
Going live
(b) Failed — the live test didn't pass
✕
The live test didn't pass

WhatsApp rejected the message send, so we stopped before activating anything.

Nothing was created No assistant, no workspace, no charge. Your setup is exactly where you left it — we rolled the whole thing back.
Try activating again
Reconnect WhatsApp first

Still stuck? Message us — we'll look at the run.

(c) Live for replies — launch message with WhatsApp
◎
“October cohort waitlist” is live

Your signup page is open and taking names right now.

One piece is still waiting Your launch message is with WhatsApp for approval — often minutes, sometimes hours, and it can take up to a day. It goes live automatically the moment they approve. Nothing for you to check.
Working nowsignup page · confirmations · your sheet
Waitinglaunch blast only
Open the signup page
See it in Pulse
(d) Live — everything on
◎
“Autumn retreat support” is live

It's answering on your WhatsApp from right now.

See it for yourself Open WhatsApp and message your own business number. You'll get the real reply, from your real Brain, in seconds.
See it in Pulse

$0.50 per session · pause anytime

(e) Template rejected — named fix path
!
WhatsApp turned down your launch message

Signups keep working. Only the launch blast is blocked until the wording is fixed.

What they flagged “Too promotional for a utility message.” WhatsApp is strict about wording on messages sent to a list.
Rewrite and resubmit
Use our approved wording

Resubmitting goes back into review — same open-ended window.

Pulse twin of (c) — Active, amber meta line
Active ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
Launch message with WhatsApp for approvalⓘ
Runs
18 · 100% healthy · 6m ago · $4.50
Pulse twin of (e) — Failed, red family
Failed ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
WhatsApp turned down your launch messageⓘ
Runs
18 · 100% healthy · 6m ago · $4.50
Signups still workingRewrite →
Story · acceptance · design notes — shared with the desktop half: frame 7 ↑ (one note, both tiers).
Live
dimmed Pulse peeks — revealGap · app header stays visible above · no exception row
Autumn retreat support✎
On-Brand Support Assistant · ASST-7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Runs this month142
Health96%
Last run2h ago
Cost this month$18.40
Your WhatsApp chat
Guests scan or tap to message you.
https://wa.me/16318181081
WhatsAppXThreadsCopy link
MystFlo
Autumn retreat support
Scan to chat on WhatsApp
Flyer card · 2048px
Print and social · Save image
Recent activitySee all ›
24h7d30d
Session — in progress***5373 · 5 turnsjust now
Answered a guest — “is the September week still open?”$0.50 · 1.1s2h ago
Guest needs you — refund questionNeeds attentionView issue4h ago
Answered a guest — “what time does check-in start?”$0.50 · 0.8s6h ago
Reactivated — same setup, same listJul 22
This assistant’s activity.
Story
  • As a founder checking On-Brand Support on a slow afternoon, I read the four numbers, tap to share my chat link if I need to, and scroll a short activity list — no full-width band eats the middle of the tab when there's nothing to book.
Acceptance
  • NEW (PRD debt) — Given a non-records, non-exception assistant's Pulse tab / When it renders / Then the body is exactly: no exception row → the fixed four metrics (Runs · Health · Last run · Cost MTD) left → the type's slot right (here: chat share row) → Recent activity full-width below, 5 rows + one “See all ›” door, no in-tab pagination bar (R37).
  • AC-BILL-01/02/03 ↗ — each session row reflects one metered charge; a re-closed session never doubles; a pure-human stretch never re-bills (unchanged from the prior Today/Earlier feed, now expressed as .al-rows).
Design notes R37 — supersedes the 2026-08-22 in-tab pagination clause
  • The template, ported verbatim from pulse.html frame 3-chat (.row/.sec-marker/.qa-linkline/.qa-share/.qa-expand/.al-ledger) — the old .mb metrics band, the “Health” third column, and the Today/Earlier .act-row feed are retired from this frame (CSS stays for other frames still using it).
  • Activity is 5 rows + “See all ›”, never a pager on the tab — the chips + ‹ Newer · Page N of M · Older › pagination now live one door over, in the new Activity sheet (frame 9f). A “Load older” append button here is a FAIL.
  • The desktop “Health rail” third column (Answered on its own / Routed to you / Couldn't finish) stays deferred (issue #2732) and is dropped from this drawing — it never shipped and doesn't belong in the template.

Archetype: assistant-detail-tabs.md. Lock: R37 (supersedes the 8-22 metrics-band/Today-feed drawing on this frame).

desktop 1180 · D-5 “Waiting on you” row is the ONE exception row, always TOP
October cohort waitlist✎
Waitlist + Launch Assistant · ASST-4B8
Active · $0.25 per run · live since Jul 21
Last run 6m ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Waiting on youSend the launch · wave 2 Review
Runs this month18
Health100%
Last run6m ago
Cost this month$4.50
Signups page live214
Your signup page
Your signup page is live — share it. Wave 2 is waiting on you above.
mystflo.com/w/october-cohort
WhatsAppXThreadsCopy link
Recent activitySee all ›
24h7d30d
New signup214 total · page live6m ago
Activated by you8:02am
This assistant’s activity.
Story
  • As a founder with a launch message waiting on me, I see it the moment I open Pulse — flagged above everything else — while my signup page keeps collecting signups underneath, live the whole time.
Acceptance
  • NEW (PRD debt) — Given a staged step is waiting (frame 12) / When the Pulse tab renders / Then the D-5 “Waiting on you” row is the ONE exception row at the very top, above the metrics — never folded into the slot, never a status-colour change (D-3 stands: still Active, still emerald).
  • Max ONE pending item, oldest wins; Review deep-links to the owning tab (D-1), the fix runs through the R35 split (frame 14).
Design notes
  • Metrics append exactly ONE outcome row (Signups) — never a second append, matching the Don'ts.
  • Two separate concerns, drawn together on purpose: the D-5 flag is about wave 2 of the launch, still waiting on the founder's review — it is NOT the same gate as the signup page's own live/pending state. This instance's page is already live (Signups · page live · 214), so the slot shows the steady-state R33 share row throughout; the flag resolves independently when the founder reviews and sends wave 2. A DIFFERENT instance whose WhatsApp template is still pending Meta approval would instead show the launch-broadcast action in this same slot per R34 (per-type content swap) — that is a distinct, earlier state from this frame, not something this frame's D-5 flag controls.

Archetype: assistant-detail-tabs.md. Locks: D-5, R37.

Records assistant — slot populated
Active ▶⏸⏹ Details →
October pottery weekend ASST-9W2
Workshop Booking · $1.75 per booking
1 connected · next session Sat 10:00
Runs
31 · 100% healthy · 2h ago · $14.00
Attendeeswho's coming, who still owes you19 booked · 5 left ›
Records assistant — sold out (amber DOT, row stays monochrome)
Active ▶⏸⏹ Details →
Spring retreat ASST-2K9
Retreat Booking · $1.75 per booking
2 connected
Runs
61 · 98% healthy · 4d ago · $21.35
Attendeeswho's coming, who still owes yousold out · 2 waiting ›
Non-records assistant — slot collapsed (On-Brand Support, the named counter-example)
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support · $0.50 per session
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
Story
  • As a founder scanning my Pulse wall on workshop morning, I read who's coming straight off the card and tap once to open the list — the card is the whole tile, nothing hangs under it.
Acceptance
  • NEW (PRD debt) — Given an assistant that passes the records test / When its post card renders on Pulse / Then the record noun + live count ("Attendees · 19 booked · 5 left ›") renders as a slot INSIDE the card, below the Runs line, and tapping it opens the detail sheet on its Pulse tab with the records sheet already open.
  • NEW (PRD debt) — Given a non-records assistant / When its post card renders / Then the slot collapses to zero height — no hairline, no empty row — and the card bottom still aligns with a records card beside it (grid stretch, metrics pinned).
  • NEW (PRD debt) — Given a guest-mode viewer / When any post card renders / Then the records slot never renders — it deep-links to a PII roster.
Design notes supersedes RecordsEntryRow under the card · Peyton 2026-09-02
  • Slot, not sibling. The shipped RecordsEntryRow (a bordered Link mounted under AssistantSummaryCardPost in Pulse.tsx) made the active wall ragged — some tiles had a tail, some didn't. The line moves INTO the card as the last zone: badge+controls → title → identity → status line → hairline → Runs → records slot → footer action. Same content as the old row: noun · sub-label · "N booked · M left" · chevron; sold out = amber dot + "sold out · N waiting", monochrome row, never a tint.
  • Collapses, doesn't reserve. R34's fixed-slot law (slot existence is fixed; contexts swap content) holds at the contract level — every post card has the slot in its DOM anatomy — but an empty records slot renders at ZERO height, not as a reserved 44px band. Precedent: the 2026-07-23 title-band deletion — a reserved empty zone on every non-records card costs whitespace the wall doesn't need. The wall's equal height comes from grid stretch + mt-auto; a non-records card beside a records card gets its extra air above the pinned metrics block, never a blank hairline row.
  • Deep link from the tile. Tap → /pulse?assistant=<id>&records=open (param name = build decision, CTO): the detail sheet opens on Pulse (R30) and the records sheet rises over it. Refresh, bookmark, second device all land in the same place — the deep-link requirement that justified the old route survives as a URL param.
  • Status ladder untouched (D-3). The badge is still the one status; the slot carries a count, never a status word. R31's "Waiting on you" flag row and this slot can coexist on one card — flag first (it's a hand-back), records slot last (it's a door).
Build gaps
  • In-card slot in AssistantSummaryCardPost (records-contract-aware, guest-gated, collapse-to-zero); retire the RecordsEntryRow mount in Pulse.tsx.
  • Card tap with the records param → open sheet + nested records sheet in one navigation (no flash of the bare Pulse tab).

Archetypes: assistant-summary-card.md (slot), records-surface.md (the way in). Lock: R36.

dimmed Pulse peeks — revealGap · URL ?assistant=4L9 · roster is the FIRST item in the RIGHT slot, above the booking link (R37 — supersedes the full-width band)
Weekly wheel-throwing class✎
Workshop Booking Assistant · ASST-4L9
Active · $1.75 per run · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Runs this month31
Health100%
Last run2h ago
Cost this month$14.00
Bookings taken this month19
Attendees 10 seats · 7 booked · 3 left · synced 2 min agoSee all 6 ›
Aisha Kone3 seats · link sent 27 Julawaiting paymentMark paid⋯
Maya Chen2 seats · booked 26 Julpaid
Tom Reyes1 seat · booked 26 Julpaid
Devi Rao1 seat · roster tickpaid
Noor Azizjoined Aug 2waiting

5 of 6 · needs-verdict first, then newest · 2 on the waiting list

Your booking link
https://wa.me/15551234567?text=Book+a+seat
WhatsAppXThreadsCopy link
MystFlo
Weekly wheel-throwing class
Scan to book on WhatsApp
Flyer card · 2048px
Print and social · Save image
Recent activitySee all ›
24h7d30d
Booking confirmed — Priya M.$1.75 · paid6:14pm
Payment link relayed — Aisha Koneawaiting payment5:30pm
Class reminder queuedNeeds attentionView issue6:00pm
Booking confirmed — Daniel R.$1.75 · paid2:05pm
Answered a guest — “is parking included?”$0.08 · 0.9sJul 20
This assistant’s activity.
Story
  • As a founder opening my workshop on Pulse, the first thing in the right column is who's coming and who still owes me — five rows I can act on, then my booking link right under it, with no full-width band pushing the activity feed down the page.
Acceptance
  • NEW (PRD debt) — Given a records assistant's post detail sheet / When the Pulse tab renders / Then the roster (Attendees · Orders · Signups) is the FIRST item in the RIGHT slot — above the booking link/share row — never a full-width band between the metrics/slot pair and the activity; a non-records assistant renders the ordinary chat/empty slot (frame 9b unchanged).
  • AC-WSBK-24 ↗ — paid rows stay listed in the roster; unpaid rows are called out by dot + verdict, never by being the only rows shown.
  • AC-WSBK-25 ↗ — the only controls on a row are Mark paid · Extend due date · Release spot; the roster never adds an editable cell.
  • AC-WSBK-23 ↗ (amendment pending — the destination is now this in-tab roster + the nested sheet, frame 9e, not the routed page the criterion text still names).
Design notes R37 (2026-09-03) — supersedes the 2026-08-22/09-02 full-width-band placement
  • Right column as principle (Peyton, 2026-09-03). The right column is THIS type's slot — one slot, per-type content. Records types fill it roster-first, then the booking link/share/flyer underneath; chat types fill it with the share row alone (frame 9b); generation types fill it with a piece-readiness preview + Open kit › (frame 9b-k).
  • Compact by contract. ≤5 rows, hairline group, de-boxed, same .act-row grammar as the activity feed below — name · seats/spots on the sub-line; status is a dot + word on the right; verdicts render only on rows that can take one.
  • No lantern here. An unpaid booking is pending (amber dot); a verdict is a domain action, not an attention item — Lantern stays D-5's one moment. The verdict button stays monochrome outline.
  • Header carries the truth line: seats · booked · left · synced-ago. "See all N ›" and the header both open the records sheet (9e). Container words (Records / List / Table / Ledger) never appear — the block title is the noun.
Build gaps
  • Roster-in-slot component in AssistantDetailModal.post.tsx's Pulse tab (records-contract-gated), fed by the same useAssistantRecords hook the retired page used — one read, feeds the slot AND the sheet.
  • Deep link: ?assistant=<id>&records=open opens the sheet on top of this tab; the old /pulse/:assistantId/records route becomes a redirect into it (not built).

Frame 9b (On-Brand Support) stays the no-records twin. Archetypes: assistant-detail-tabs.md, records-surface.md. Locks: R36, R37.

dimmed Pulse peeks — revealGap · “Open kit ›” goes to the existing review sheet (program-launch-kit.html sec-8), NOT this template's own sheet
Sunrise Yoga Retreat✎ASST-M3K9
Workshop Launch Kit · active since Aug 30
✕
Pulse Overview Personalize Connect
Runs this month1
Health100%
Last runAug 30
Cost this month$3.00
Your kitOpen kit ›
Description
The short paragraph for your listing or booking page
Page copy
The full page — headline, the days, what's included, how to book
Launch blast
The email or broadcast that opens it
IG captions
Three, to post across the launch week
Flyer copy
Short-form, for print or a story card

All 5 pieces · v1 · $3.00 kit + $0.02 rewrites. Open kit › to read, rewrite what's off, and take it with you.

Recent activitySee all ›
24h7d30d
Kit written — v1, all 5 pieces$3.00Aug 30
IG captions rewritten — v2$0.02Aug 31
Page copy saved to DocOpen DocAug 31
This assistant’s activity.
Story
  • As a founder checking my launch kit on Pulse, I see which pieces are ready and which I flagged, and one tap opens the real kit surface where I read, rewrite, and take it with me — the tab itself never tries to BE that surface.
Acceptance
  • NEW (PRD debt) · amends the 2026-08-22 generation-kit exception — Given a generation-kit assistant's Pulse tab / When it renders / Then the FIXED four metrics (Runs · Health · Last run · Cost MTD) render on the left same as every other type, and the right slot shows a short piece-readiness preview (title · status word) with one “Open kit ›” door to the existing LaunchKitReviewSheetBody — the tab no longer trades its whole body for that sheet.
  • AC-BILL-01 ↗ — the Cost MTD figure is the one settled kit debit: exactly one `debit_wallet` charge at `price_per_run` fires once ≥1 piece delivers and every piece reaches a terminal state, so a partial kit still shows the fixed kit fee, never a per-piece tally.
Design notes Amends the 2026-08-22 pulse.html note "Generation-kit keeps LaunchKitReviewSheetBody as its full body"
  • The kit body no longer replaces the Pulse tab. Peyton's 2026-09-03 "right column as principle" ruling makes generation a typed slot like chat and records, not a full-tab swap — this frame is the amendment. Open kit › is the one doorway into program-launch-kit.html sec-8's review sheet; nothing about that sheet's read/rewrite/take-away mechanics changes.
  • Piece rows are read-only status, never editable here — rewriting a piece only happens inside the review sheet's composer.
  • No run controls (▶⏸⏹) — a kit instance has no continuous running state, matching program-launch-kit.html sec-7's existing note.

Archetype: assistant-detail-tabs.md. Lock: R37.

the detail sheet (9b-r) recedes behind — nestedBackdrop rgba(8,8,10,.96) + blur · Escape / ✕ close THIS sheet only (broadcastCloseAll={false}) · URL ?assistant=9W2&records=open
Attendees · October pottery weekend
24 seats · 19 booked · 5 left · synced 2 min ago
✕
Awaiting payment Waiting list zero selected = everyone · no "All" chip (FilterChipGroup)
NameContactSpotsBookedStatus
Who's coming · 19
Sam Idrissam@idris.co1link sent Aug 30awaiting paymentMark paid⋯
Lena Ortizlena@ortiz.studio2Aug 31paid
Priya N.phone only1Aug 31paid
Tom Reyestom@reyes.co1Aug 30paid
Maya Chenmaya@studio.co2Aug 29paid
Devi Raodevi@rao.studio1roster tick · Aug 28paid
… 11 more on this page (20 rows per page)
Waiting list · 3
Aisha Konephone only—joined Sep 1waiting
Sam Oyelaranphone only—joined Sep 1waiting
‹ PrevPage 1 of 2Next ›
The other four states — same sheet, same band, cropped to 560
Attendees · October pottery weekend
24 seats · 0 booked · 24 left
✕
◦
No one's booked yet

Your booking link is live. Share it and the first name lands here — usually within a day of posting.

Copy your booking link
Empty. No filter chips, no column headers over an empty body — absent, not disabled. The in-tab block behind it shows the same line in one row.
Attendees · October pottery weekend
✕
NameContactSpotsBookedStatus
Loading. Skeleton rows at the real 40px grid height so nothing jumps on resolve; headers are drawn (structure the fetch can't change); aria-busy="true"; shimmer off under reduced motion.
Attendees · October pottery weekend
24 seats · 19 booked · 5 left · last loaded 6 min ago
✕
Couldn't refresh — showing the list from 6 minutes agoRows below may be out of date. Try again
NameContactSpotsBookedStatus
Sam Idrissam@idris.co1link sent Aug 30awaiting payment
Lena Ortizlena@ortiz.studio2Aug 31paid
Warm-stale. A refetch failed over rows already on screen: rows stay, dimmed, their age named, and the verdict buttons are REMOVED — acting on stale state is how a seat gets double-released. Never blank a list the founder is reading.
Attendees · October pottery weekend
24 seats
✕
!
Couldn't load your attendees

Nothing's lost — this is a connection problem on our end. Your bookings are safe.

Try againClose

Or ping us if it keeps happening.

Cold error. Nothing ever loaded: full-body state, retry primary, Close returns to the Pulse tab beneath. Red is earned here and nowhere else on this surface.
Story
  • As a founder who tapped "See all", the whole list rises over the tab I was on — I filter, page, mark someone paid, and close back to exactly where I was; the URL remembers the sheet so tomorrow's bookmark lands here too.
Acceptance
  • NEW (PRD debt) — Given the records block's "See all" / header, the in-card slot, or the URL ?assistant=<id>&records=open / When resolved / Then the records sheet opens stacked over the post detail sheet's Pulse tab with the detail sheet still mounted beneath; ✕ and Escape close only the records sheet; refresh, bookmark, and a second device reopen it. (Replaces the AC-WSBK-23 "same full-screen destination" wording — amendment pending.)
  • AC-WSBK-27 ↗ — waitlist rows group beneath attendees in every tier; Spots reads "—", Contact "phone only".
  • AC-WSBK-32 ↗ — warm failure keeps stale rows (dimmed, aged) and strips verdicts; the list is never blanked.
  • AC-WSBK-28 ↗ — a paused assistant renders every state unchanged.
Design notes supersedes records-surface.md (b) "PageSlideOver … has no URL" ban · workshop-booking sec-13 "Routed page, not a slide-over" · Peyton 2026-09-02
  • A nested content sheet, not a route and not a PageSlideOver. ModalWrapper presentation="sheet" with nestedBackdrop + broadcastCloseAll={false} (playbook §3 stacked-modal props), contentWidth="wide" so the grid uses the sheet; z-index above AssistantModalShell (build gap). The full-width sticky .sheet-header band carries title = noun · instance name, subtitle = the truth line, and the ✕ close control (44×44). The deep-link reason that justified the route survives: the sheet has a URL via the param.
  • Filter + pagination reuse the platform idiom: FilterChipGroup (icon-free chips, zero selected = unfiltered, no "All" chip) and PaginationBar sortable (‹ Prev · Page N of M · Next ›, right-aligned, hidden at ≤1 page, 20 rows/page, client-side). Never a third pagination or filter style.
  • Structure steps at lg 1024 only — the 6-column grid inside the sheet; below it the identical rows stack (9e-m), no column dropped. Group rows are hairline eyebrows; rows are de-boxed; status is a dot + word; sold out is a state, never a tint; red only on a genuine load failure.
  • Read + verdict, never edit. Mark paid · Extend due date · Release spot, gated to the rows that can take one, in DOM row order as real buttons; no editable cell, no global list, no cross-assistant merge, no identity join. Sign-in and not-owner states: 9e-m.
Build gaps
  • Route redirect — /pulse/:assistantId/records → /pulse?assistant=<id>&records=open; AssistantRecordsPage retires once the sheet ships.
  • Nested sheet — RecordsSheet on ModalWrapper over the detail shell, reusing RecordsTable / RecordRow / RecordsEmptyState as-is; FilterChipGroup + PaginationBar wired.
  • Warm-stale rule — stale rows keep rendering with verdicts stripped inside the sheet AND in the in-tab block (one hook, one stale flag).
  • Deep-link param — ?records=open persisted like ?assistant= / ?handover=; cleared on close; ignored when ?assistant= resolves nothing.

Tablet 768 not drawn in this file — the records-surface archetype's 768 rule holds (shell from desktop, rows still stacked, verdicts inline); workshop-booking.html 13b draws it. Archetypes: records-surface.md, sheet-slide-panel.md. Lock: R36.

the detail sheet (9b/9b-r/9b-k) recedes behind — nestedBackdrop + broadcastCloseAll={false} · the chips + pagination the tab's 5-row preview doesn't carry live HERE
Activity · Weekly wheel-throwing class
This assistant’s activity · 38 events in 7d
✕
24h7d30d
Booking confirmed — Priya M.$1.75 · paid6:14pm
Payment link relayed — Aisha Koneawaiting payment5:30pm
Class reminder queuedNeeds attentionView issue6:00pm
Booking confirmed — Daniel R.$1.75 · paid2:05pm
Answered a guest — “is parking included?”$0.08 · 0.9sJul 20
Sheet sync failed — Google Sheets didn’t respond in timeNeeds attentionView issueJul 19
Booking confirmed — Aisha Kone3 seats · link sentJul 19
Answered a guest — “is there parking on site?”$0.08 · 1.1sJul 18
Reminder sent — tomorrow’s class7 confirmedJul 18
Booking confirmed — Maya Chen$3.50 · paidJul 17
Resumed by youJul 17
Activatedfirst run passedJul 17
‹ Newer Page 1 of 4 Older ›
This assistant’s activity.See account-wide runs →
Two more states — same sheet, same band, cropped to 380
Activity · Weekly wheel-throwing class
✕
Loading. Skeleton rows at the real 40px row height, chips skeletoned too; shimmer off under reduced motion.
Activity · Weekly wheel-throwing class
Nothing yet
✕
◦
Nothing yet

Runs show up here as they happen.

Empty. No chips, no pagination bar — absent, not disabled. Same copy the tab's own activity block shows in one row.
Story
  • As a founder who tapped “See all” on the activity feed, I get the full history in one place — the same 24h/7d/30d chips and the paging I used to hunt for on the tab, now living where they belong.
Acceptance
  • NEW (PRD debt) — Given the Pulse tab's activity block's “See all ›” / When tapped / Then a nested sheet rises over the tab (detail sheet still mounted beneath, nestedBackdrop, broadcastCloseAll={false}), showing the range chips, the full .al-ledger history, and ‹ Newer · Page N of M · Older › pagination — none of which render on the tab itself.
  • NEW (PRD debt) — Given zero events / When the sheet renders / Then it shows the quiet empty state, no chips, no pagination bar (absent, not disabled).
Design notes R37 (2026-09-03) — new frame, closes the "where did the chips/pager go" gap
  • The tab's activity block is a preview, this sheet is the record. 5 rows + “See all ›” on the tab (frames 9b/9b-x/9b-r/9b-k); the range chips and ‹ Newer · Page N of M · Older › pagination move here entirely — a pager on the tab itself is a FAIL (assistant-detail-tabs.md self-check 21).
  • Same nested-sheet mechanic as the records sheet (9e): ModalWrapper presentation="sheet", nestedBackdrop, broadcastCloseAll={false}, contentWidth="wide" — one mechanic, two content sheets on the same tab.
  • Row grammar is the unchanged .al-ledger shape (source mark already dropped) — no new row component for the fuller list.

Archetype: assistant-detail-tabs.md, sheet-slide-panel.md. Lock: R37.

Peyton reversed the read-back ledger the same day it shipped: "keep the same design as the pre-activation, just show as saved text or selected — but as a preview, and can't be click." This frame IS that instruction, literally — same categories, same numbered .sm group headings, same .field-label / .field / .opt-radio row anatomy as the Configure step (workshop-booking.html sec-3b), reused unchanged. The only delta from Configure is the .pz-locked wash (Peyton: "maybe gray-out shade colour") and the removal of every click handler — no Edit, no per-row verb, on ANY row, Safe tier included. The A6 Safe/Structural/Identity split (fieldEditPolicy.ts) stops being a DISPLAY concept: every field renders through the exact branch ConfigFieldRenderer.tsx already ships for field.locked template-text (~L863) — read-only preview, no customize affordance — generalized here to text/radio/select. Drawn on the Workshop Booking instance from Peyton's 2026-09-03 live test.

ACTIVE — at rest · header is frame 9g's four lines (Paused renders the identical body — header state is the only delta, see the crop below)
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Pulse Overview Personalize Connect

This is what's set for this round — nothing here can be edited in place. To change any of it, start fresh with a new assistant → (the ⋯ menu, top right). Brain readiness lives on Connect →

01 · Your workshop
Workshop name
Saturday Sound Bath Workshop
Workshop date
Sat Feb 9, 2026 · 11:00
Price per seat
USD45
Total seats
12
03b · Where guests book

Both options still show — the picked one just reads selected, not tappable.

In this chat
WhatsApp's own tap-through form.
Your own booking form
Bookings land in your sheet, you tick paid there.
04a · Booking messages
Payment ask — the founder's own wording, verbatim
Your seat is held — it's confirmed the moment your payment lands. Reply here once it's sent and I'll check it off myself.
Booking confirmation locked
Meta-approved · not editable
You're booked, Maya — see you Feb 9 at 11:00.

Same box, same wash, as the Safe payment-ask field above it — pre-activation already drew this exact "locked" style for Meta templates. Nothing new; the whole tab now reads this way.

03a · Where guests reach you
Booking link
wa.me/15551234567?text=book

Runs on demand — whenever a guest messages this number.

·· preview — “In this chat” · once your Flow is live ··
hi! any spots left for tuesday's class?
Wheel Throwing Class — Jul 28, 2026. Tap below to grab your spot:
Wheel Throwing Class
Tue 28 Jul · $42 per seat · 3 seats left
Name
Email
Party size
2026-07-28
Confirm booking
Real form fields after activation — never faked here
Your details are in, Maya. Your seat for Wheel Throwing Class is held — it's confirmed the moment your payment lands.

Here's how to pay for your spot — reply once you've sent it and I'll confirm.
↗ Pay now
When “QR code” is picked (04b), this bubble sends instead:
your QR as an image — the same payment-ask words as its caption
done — just sent it!
you tap Mark paid — or your roster shows it
You're booked — Wheel Throwing Class
Hi Maya, it's Priya — your seat for the Wheel Throwing class is confirmed. We'll send a reminder before class. Reply here with any questions.
Then: the Class reminder (04a) — same thread, 1 day + 1 hour before class

Works the same whether they tapped your wa.me link or typed this directly — the AI reads intent, not just the word.

·· preview — “Your own booking form” (03b) ··
hi! any spots left for tuesday's class?
Yes! Here's where to book: forms.emberclay.com/wheel — you'll pick your spot and pay there. Shout if anything's unclear.
That relay is the whole guest experience — no capture, no payment ask (AC-WSBK-14). Confirmation + reminders fire from your roster tick.
PAUSED — same fields, header only differs (compare to 9g)
desktop 1180 crop — header swap only, body below is byte-identical to Active
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Paused by you · $1.75 per run · live since Sep 2
Paused Sep 4 · nothing goes out
▶⏸⏹⋯✕

Pause is no longer a prerequisite for editing anything — there is nothing left on this tab that pausing would unlock. It stays what it always was: stop the assistant from running. "Start fresh with a new assistant" works from Active too (frame 9g's ⋯ menu note: "This one keeps running until you stop it").

A field the founder never filled — schema default vs honest "Not set yet"
desktop 1180 crop — Total seats left blank at signup
Total seats
Not set yet

Never a silent schema default. formatLockedFieldValue() already returns exactly this string for null/undefined (ConfigFieldRenderer.tsx L194-200) — reused verbatim, not invented. Showing a default as if the founder chose it would break the honesty line ("sounds like you — because you confirmed it does"): a value nobody confirmed isn't a fact yet, so it can't read as one.

Story
  • As a founder opening Personalize on my live assistant, I see the exact form I filled out at signup, in my own words — nothing shouting "locked", nothing inviting a tap. One line at the top tells me the only way to change it.
Acceptance
  • AC-LIFECYCLE-11 ↗ — PRD amendment owed, policy-level (not just wording): the AC's "Structural fields stay locked while Active and unlock on Pause; Safe fields stay editable while Active" is retired outright, not just its presentation clause. Under this lock nothing edits in place in ANY status — Active and Paused render the identical read-only body. The AC needs rewriting to say that, in the same PR as the build.
  • AC-LIFECYCLE-12 ↗ — Identity fields never edit in place, in any status. Still true, now true of every field, not identity alone. The "Start fresh with a new assistant" pointer lives in the single top context line + the header ⋯ menu, never per-row.
  • NEW (PRD debt) — no field on this tab is ever clickable. ConfigChangeConfirmModal, saveInstantField, and the whole batch dirty-state bar have no caller left on this tab — see the "Build" note below.
  • NEW (PRD debt) — an unfilled field shows formatLockedFieldValue()'s existing "Not set yet" fallback, never a silent schema default.
Design notes Peyton reversal, 2026-09-04 — same afternoon as the ledger it replaces
  • Not a new grammar — the OLD one, muted. The retired frame invented a receipt-style .row .l .r ledger unique to post-activation. This frame reuses the Configure step's own components (.field-label/.field/.opt-radio) byte-for-byte — a founder who filled the form once recognizes it instantly on the way back in.
  • The wash is the only tell — and it's form-only. .pz-locked (opacity .84, saturate .9) is the one visual delta from an editable Configure step — Peyton's own "gray-out shade colour" instruction — applied uniformly across the .form-col, never per-row (a field is not "more locked" than its neighbor). It stops at the form column's edge; see the preview-rail note below for why the .pv-col is excluded.
  • Radio/select stay full groups. The chosen option keeps .opt-radio.sel's filled dot among its un-picked siblings — recognition of what the choices WERE matters as much as which one was kept. Collapsing to a single value line (the retired ledger's move) is what made it read as a novel grammar instead of a mirror.
  • Generalizes past booking. On-Brand Support has no Structural/Identity fields today, but "nothing is interactive" is unqualified — its chip groups and Slack-notify switch ALSO stop being D-2 instant-save on this tab under this lock (a wider consequence than the booking case; flagged for the per-template revisit card, not fixed here).
  • Preview rail restored, 2026-09-04 — Peyton reversal of the reversal, same day. The redraw above dropped the pre-activation split-pane's .pv-col entirely; Peyton caught it and was explicit: "keep the same design as the pre-activation, just shown as saved text or selected but as a preview and can't be clicked." That means the live-preview column stays too, not just the form.
  • Correction, same day — the preview column is IDENTICAL pre/post, never dimmed. Peyton: "The preview is a static design visualisation - so pre and post activation - just have it stay the same." The .pv-col here is a byte-for-byte copy of pre-activation's own preview column (workshop-booking.html sec-3b — same Wheel Throwing Class sample, same both-variant stack, same "once your Flow is live" copy, same opacity on the unpicked-variant phone) — not restyled, not dimmed, not re-derived from 9c's own saved values. .pz-locked now sits on .form-col only (the fields/radios/inputs), never wraps .pv-col — the read-only wash is a form-column property, not a tab-wide one. The static preview illustration doesn't change just because the assistant went live, so it doesn't get a second "sample" label either — it reads exactly as it does pre-activation.
  • Tension with the older Personalize-vs-Try rule, named not buried. A 2026-05-20 lock ([[feedback_personalize_vs_try_separation]]) reads "Personalize never contains preview; Try owns preview" — on its face this frame violates it. It doesn't, in practice: that lock targeted a specific failure (a hosted-page URL/rendered-result block bleeding into TMPL-WAITL1's Personalize) and predates T1053 + the R32 2026-07-28 amendment, which added the live-preview CHAT split-pane to pre-activation Personalize on purpose and was itself locked 2026-06-20 ("post-activation detail modal = visual TWIN of pre… live-preview split-pane in Personalize"). This frame just keeps that later, narrower preview-species identical between pre- and post-activation (not just in sync — literally the same markup) — it does not reopen hosted-page/URL previews on Personalize, which the May lock still correctly blocks. Both rules stand; they govern different preview shapes.
Build
  • ConfigFieldRenderer.tsx: the editLock branch (~L341-374, "Pause to change" / "Start fresh" per row) is deleted entirely, not simplified — its job (label + value, no button) already exists as the field.locked branch used by TemplateTextField (~L863); extend that same "no customize affordance" behavior to RadioField/SelectField/plain text so ONE locked path serves every type. AssistantSettingsTab.tsx: INSTANT_SAVE_RADIO_KEYS, saveInstantField, and the mounted ConfigChangeConfirmModal lose their only caller on this tab — remove them from the post-activation render path (they may still matter to ConfigureStep.tsx pre-activation, which is untouched by this lock).
  • Tests to amend: ConfigFieldRenderer.editLock.test.tsx, AssistantSettingsTab.editGating.test.tsx — both assert the now-fully-retired "Pause to change" / inline-Edit behavior, not just its strings. AC-LIFECYCLE-11/12 wording in prd-pl-assistant-lifecycle.md in the same PR.
  • Preview rail: mount the SAME PreviewPanel/getPreviewRenderer pair `ConfigureStep.tsx` already renders pre-activation (the 2026-06-20 twin lock's "same getPreviewRenderer/personalizeFirst gate as pre"), fed the persisted config instead of in-progress form state. Do NOT wrap it in pz-locked or any other dimmed/read-only container (correction, same day — Peyton: "the preview is a static design visualisation... just have it stay the same") — it renders at full, unmodified opacity, identically to how ConfigureStep.tsx already renders it pre-activation. Only the typing-reactive affordance is inapplicable here (no cursor, no "live" pulse on the greeting bubble) since nothing on this tab accepts input — that's a behavioral no-op from having no in-progress form state to react to, not a visual dimming choice.

Spec: prd-pl-assistant-lifecycle.md §A6 (amend). Archetype: assistant-detail-tabs.md § 2026-09-04 locks (superseding entry). Mobile: 13c ↓. Tablet 768: not drawn for this frame — when it is, follow this file's own D2-locked progressive pattern (sec-4e ↑: split engages where width allows, else the mobile pattern holds); the form column stays pz-locked like the two tiers drawn here, the preview column stays undimmed like pre-activation.

The header answers four questions in order, one line each: what is this one about (subject) · what kind of assistant is it, and which (spelled-out type + id) · what state is it in (status · price · since when) · what is it doing right now (activity). Health is not in the header — the Pulse tab's fixed Health row is its one home. Trigger type (“On-demand”) is setup, not state — it reads at the foot of the Personalize tab. The type word never appears twice: the auto-name stops embedding the template name at the source (instanceNaming.ts), so L1 is the subject alone.

Booking type — named by its subject
desktop 1180 crop — header + tab strip
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
L1 subject (the founder's word or the program name) · L2 type + id · L3 status dot + label · price · live since · L4 activity only (“Chatting now” / “Last run 2h ago” / “No runs yet”). Pencil renames L1 only. The id is mono, quiet, on L2 — off the title.
No subject yet — L1 falls back to the type
desktop 1180 crop — the fallback branch
On-Brand Support Assistant✎
#7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
A support assistant has no program to be “about”, so until the founder names it L1 is the spelled-out type and L2 is the id alone — the type is never printed twice. Once named (“Autumn retreat support”), it renders exactly like the booking crop: name · “On-Brand Support Assistant · #7Q1”.
Paused by us (wallet) — status colour on L3 only
desktop 1180 crop — system pause · D-3 ladder unchanged
Autumn retreat support✎
On-Brand Support Assistant · #7Q1
Paused — wallet empty · $0.50 per session · live since Jul 21
Last run yesterday
▶⏸⏹⋯✕
The only coloured ink in the header is L3's status (D-3: amber = paused by us / wallet, red = Failed, emerald dot = Active, neutral = paused by you / stopped). Nothing else in the header carries a colour or a verdict — “Needs attention” never appears here; the Pulse tab's Health row and the “Waiting on you” exception row (D-5) own that. Run row: ▶ live (resume), ⏸ off (already paused), ⏹ live — D-4 fixed-order, dimmed-not-removed.
The ⋯ menu — Rename and Start-fresh moved here
desktop 1180 crop — menu open · same .smenu species as 9d's status menu
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Rename
Start fresh with a new assistant →
A new instance, new id, prefilled from this one. This one keeps running until you stop it.

Two items, deliberately. Run / Pause / Stop stay the A5 icon controls (▶ ⏸ ⏹, D-4 fixed order) — the menu never duplicates them. “Switch account…” stays in Connect's status menu (9d lock). The Personalize tab's “start fresh with a new assistant →” link opens this same chooser (frame 13's Reactivate/Start-fresh dialog), so there is one Start-fresh door, reached two ways.

Story
  • As a founder opening any live assistant, I read in one glance what it's about, what kind it is, whether it's on and since when, and what it's doing right now — the same four lines whether it's my support assistant, a workshop, a retreat, or something MystFlo ships next year.
Acceptance
  • NEW (PRD debt) — the post header renders exactly four lines in this order for every template; the template/type word appears once (L2), never inside L1.
  • NEW (PRD debt) — no health verdict renders in the header; `getHealthInfo` output is consumed by the Pulse tab's Health metric row only.
  • NEW (PRD debt) — the auto-generated instance name is the subject alone (`cohort_name` / `program_name` / the founder's name), never prefixed with the template name; existing instances whose stored name matches the old `Template (subject)` pattern render L1 as the subject (display-side strip, no data migration).
  • PRD amendment owed — prd-pl-assistant-lifecycle.md “Display ID” row (§ identity sub-line: “template name · ASST-…, template name omitted when it matches the display name”) describes the D-4 sub-line this frame retires; rewrite it to the four-line contract.
Design notes amends D-4 (2026-07-23) — identity flip kept, template word demoted to a spelled-out TYPE
  • L1 is the subject, never the type. Booking → program name. Support (no subject) → falls back to the type name, and then L2 is the id alone. Not the customer name — a booking assistant serves many guests; the program is what tells two instances of one template apart.
  • L2 spells the type out (“Workshop Booking Assistant”, “On-Brand Support Assistant”) — a founder should never have to decode a bare catalog word. Id is mono, quiet, here — off the title line.
  • L3 is state in one grammar for every type: dot + status label · price (R27 plain text, never a pill — the pill is retired here) · “live since <date>” from createdAt. The dot is the only colour in the header.
  • L4 is activity only — pulseLastRunSlotText. Health leaves (the Pulse tab's fixed four already carry it — printing it twice is what made a 1-run sample shout). Trigger type moves to the Personalize tab's foot.
  • Run row is fixed-order, dimmed-not-removed (D-4, ../mystflo-kit/design-decisions.md): ▶ ⏸ ⏹ always render in that order, then ⋯, then ✕ — never a swap. The inapplicable control gets .run-ic.off (dim, no hover) instead of disappearing: Active → ▶ off; Paused → ⏸ off. Matches shipped code (AssistantDetailModal.post.tsx ~L1583, disabled= + aria-label="Already active") and the summary card's own A5 rule (.p-controls span.off) — this frame previously drew a swap and would have regressed working code if built verbatim.
Build
  • Shared primitive: evolve IdentitySubline (AssistantCardPrimitives.tsx L78-105) into a PostIdentityBlock that renders L1-L4 from { name, subject, displayType, displayId, status, pauseReason, costPerRun, createdAt, activity }; the post card keeps using the same primitive so card ↔ modal never drift (D-4's original point). Header markup: AssistantDetailModal.post.tsx L1466-1558 — delete the meta line's health span and the trigger-type span.
  • displayType: presentation-layer, no migration — src/lib/instanceNaming.ts gains getDisplayType(templateId, templateName) = a small override map (WSBK01 “Workshop Booking Assistant”, EVBK01 “Event Booking Assistant”, RTBK01 “Retreat Booking Assistant”, 9P3X “On-Brand Support Assistant”, WAITL1 “Waitlist + Launch Assistant”) with fallback `${templateName} Assistant`. Same file, L118/L124: return the subject alone, not `${templateName} (${subject})`. A display-side strip handles already-stored names.
  • Not this batch: forcing a naming moment at activation (#4432 explicitly deferred) — the fallback branch is what makes deferring it safe.

Archetype: assistant-detail-tabs.md § 2026-09-04 locks (post header). Card twin: assistant-summary-card.md D-4 note. Mobile: 13g ↓.

Post-activation adds one thing to frame 5b's contract: a run-status risk. Switching a connection mid-run can land a message or a charge on the wrong account, so while the assistant is Active the Switch-account item is muted — visible, still tappable, and it explains itself. Everything else is 5b unchanged: one control species, chevron inside, impossible actions greyed rather than removed. 375 first, then desktop.

Mobile tier for this frame lives with the rest of the phone journey — 13d · mobile ↓ (one note, both tiers; the file's §5 desktop / §6 mobile split).

ACTIVE — "Switch account…" muted in the menu, tapped to show why
desktop 1180 crop — Connect tab, post-activation
October cohort waitlistASST-4B8
Connect · active since Jul 21
Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌄
Payment Stripe
Takes the deposit for this booking
Connected ⌃
Disconnect
Switch account…
Pause to switch this connection Switching mid-run risks a deposit landing on the wrong Stripe account. Pause this assistant to connect a different one — or, if this connection is wrong entirely, start a new instance instead.
Pause to switch Start a new instance →

No standalone "Switch account" button (T1164 retired) and no badge caret — one app in play per role here, so the badges carry nothing. Both rows still carry their status chevron, because the status button always has something to say (5b's pass-3 rule). The action lives in that menu; while Active it stays visible but MUTED, and tapping it opens this notice instead of acting. Reconnect (same-account repair) is unaffected and still appears if a connection breaks.

PAUSED — "Switch account…" live, choosing it opens the real switch
desktop 1180 crop — Connect tab, post-activation
October cohort waitlistASST-4B8
Connect · paused by you · Jul 29
Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌃
Disconnect
Switch account…
WhatsApp Business
○Use a different number
Opens Connects to link a different WhatsApp number — the same reconnect flow, a different account
Payment Stripe
Takes the deposit for this booking
Connected ⌄

Paused (or Stopped) lifts the mute — the menu item goes live and resolves through the existing verdict-matrix mechanic (ALLOW / ALLOW+REPROVISION / HARD-BLOCK), then Resume. On a MULTI-app row this item greys out with its reason and points at the badge, exactly like Disconnect does (frame 5b) — the row-level control never guesses which account she meant.

A6 amended three times — the action now lives in the STATUS menu Peyton, 2026-08-06 → 08-09 → 08-10
  • 2026-08-10 (pass 3) — the muted item is the .dim flavour, and that survives 5b's new greyed-item rule rather than collapsing into it. 5b's .off is "cannot act, here's why" as a flat inline line. This item is different in kind: it IS tappable, and what it opens is a decision with two live paths ("Pause to switch" / "Start a new instance →"). The dividing rule, now written once for the whole system: a reason that carries actions gets the notice panel; a reason that is purely informational gets the inline line. Mobile mirrors added this pass — 9d was desktop-only, which canon U8 doesn't allow for a signed frame.
  • 2026-08-09 (supersedes the 2026-08-06 badge-caret shape): under the two-control ruling the badge is the APP PICKER only — account lifecycle never lives behind it. "Switch account" therefore folds into the STATUS button's menu (T1164 standalone button stays retired), as a sibling of Disconnect/Reconnect. The muted/live third state transfers with it: the menu item is visible-but-muted while Active (tapping it opens the explainer, never acts) and live once Paused/Stopped. Single-app badges here carry NO caret at all — nothing to pick between. shipped 2026-08-17 — Switch account lives in the status menu; Active mutes it into the pause-or-new-instance notice.
  • Supersedes the original A6 shape (Peyton-approved 2026-08-02). A6's separate "Switch account" `.btn-outline` beside the Connected pill never existed pre-activation — two UIs for one job. One mechanic now serves both phases: the status menu.
  • The risk reason is unchanged and still enforced — reconnecting to a different account mid-run risks in-flight messages/charges landing on the wrong one. What changes is HOW that's expressed: not a hidden control, a MUTED one — the menu item stays visible (the row never silently loses its affordance) but opens an explanation + two real paths forward instead of acting.
  • Two paths, both real today: "Pause to switch" routes to the existing pause action, after which the caret goes live (Paused panel, left). "Start a new instance" is plain re-activation from Explore — nothing special, just the normal path for a founder whose connection is wrong enough that fixing THIS instance isn't the right move.
  • Reconnect (same-account repair — expired token, dropped auth) stays available in EVERY state, Active included, completely unaffected by this change. The two verbs still never merge: Reconnect fixes the account you have, the caret's picker changes which one it is.
Build
  • First post-activation Connect tab frame in this file — gap-fill, cropped to the apps section only. The full post-Connect tab (wallet row, Brain Check column per D-1) is not yet drawn as its own frame.
  • Crop scope — read these two rows as a sample, not the row inventory. The crop shows only Communication/Payment because the caret's three states are the mechanic under demonstration. AI Model and Storage (per B3) are omitted from the crop, not absent from the tab — the full shape is frames 5/17/18; their caret behavior post-activation is unchanged from frame 5b (Storage stays live always, AI Model stays absent always — neither carries a run-status risk).

Spec: prd-pl-assistant-lifecycle.md §A6 (to be updated to this shape). Archetype: assistant-detail-tabs.md.

dimmed Pulse peeks — revealGap · app header stays visible above (C1)
Send the launch
October cohort waitlist ASST-4B8 · Waitlist + Launch
✕
What they'll get
As it arrives in WhatsApp
Hi Ana — October dates are open. You're on the early list, so you've got first pick until Friday. Here's the link to hold your place: salt-and-stone.com/october

— Mara, Salt & Stone

Ana's name is filled in per person. Wrong words, wrong dates, wrong link? Edit in Personalize → — this screen only reviews, tests, and sends.

Before it goes
✓Your message is written
✓WhatsApp is connected
✓Wallet has enough for this send
Try it on yourself first shipped
Send a test to my own numberThe intended affordance, drawn so the build has a target. Today the field it needs is rendered nowhere — see the note. Send test
Which waves
○Wave 1 — early list
96 · sent Jun 30
sent
✓Wave 2 — October open
118 new · 4 from sold-out
214
See the 214 →
This send
Going to214 people
Band101–500 people$0.50
Already messagedNobody gets a wave twice96
Send to 214 people · $0.50

This can't be unsent, and there's no retry. Nothing goes out until you tap it.

R31 — The pattern
  • “Waiting on you” = a step the assistant hands back (review signups, approve message, fire broadcast) — part of the run, not a second wizard.
  • WAITL1 is the ONLY shipped staged assistant today (code audit, 2026-07-22) — PRLG01/RTBK01 have no founder-facing approve step; Workshop Kit/Get Found are specified-not-built. Pattern defined here for future ones (candidate verbs, none shipped: Publish the listings · Open the next cohort · Send this workshop's kit).
  • Repeats, not a milestone: row returns every time a new wave is ready, disappears once sent (`WaveBreakdown.tsx`).
Pricing — tiered by recipient count
  • Bands: 1–100 → $0.20 · 101–500 → $0.50 · 501–2,000 → $1 · 2,001–10,000 → $3 · 10,001+ → $7, billed for the whole send (`resolveTierPrice`). Confirm shows the resolved amount for THIS send, band named beside it — never a per-run figure. Zero recipients = no charge.
Build flags shipped 2026-08-17
  • Dry-run test-send shipped 2026-08-17 — number field lives on BroadcastControl (`test_phone` stays hidden from Personalize).
  • Meta approval gate shipped (G4 / P8b). Dry-run number field shipped 2026-08-17 on BroadcastControl.
  • No retry button, deliberately — billing dedup keys off the execution-log row; a retry risks a double send to real customers.
Surface 1 · A6 — Card flag
  • Flag on the existing card, not a new status — badge stays Active/emerald (D3 ladder unaffected). Max ONE pending action, oldest wins.
  • Row structure: eyebrow on its own line, message below with a real gap, Review right-aligned and vertically centered — no run-on text.
Surface 2 — Action sheet
  • ONE screen, one approve, no wizard — restyled from shipped `BroadcastControl.tsx` + `BroadcastConfirmationModal.tsx` + `WaveBreakdown.tsx`: wave selection → pre-send checklist → recipient review → message preview → resolved price → no-undo warning → send.
  • Not a second config editor — launch message/details are edited in Personalize (frame 11); “wrong words?” routes there. A Connect-tab fix (app/wallet) routes through the R35 split (frame 14).
  • Scope guard: never a task inbox/CRM, never a fifth Pulse tab.

One mechanic — PageSlideOver, one target union, one settle, one return promise ("your setup is untouched") — but not one geometry. Apps and funds slide in as 60/40 page panes, because the founder is doing a small errand and the assistant sheet beside it is the context she needs. Brain takes over the whole screen, because she is reading and correcting her own playbook — a book does not fit in 40% of a viewport, and the beat that matters (seeing her chapter fill in) is invisible in a column. Production already draws the line here: PlaybookBookPage renders createPortal(<div class="ink-book fixed inset-0 bg-black">) at z 10300, while the apps/funds targets render as panes. Same plumbing, different shape — corrected 2026-09-12 after this frame drew all three alike.

(1) Brain destination — the exception: a full-cover TAKEOVER, not a 40/60 split (Peyton 2026-09-12). The REAL Book covers the whole viewport with the Teach bar, landing on chapter 05 (the one the Policies row needs); the assistant sheet stays mounted underneath and is never visible. Not a co-edit form, and not a page pane
Close·Your playbookv3
05Assistant reads
How you run

Refunds, deposits, and changes — in your words. Your assistants quote these directly.

Your policies — what it covers · the rule you actually apply
01a policythe rule
02a policythe rule
03a policythe rule

Nothing here yet — this is the shape it takes. Teach your Brain ›

Close takes you straight back to where you were — your setup is untouched

Teach your Brainadd · change · remove
(1b) Taught and Read — she sees chapter 05 updated in her own book, still in the takeover. Drafted until Save to Brain (v5.27). Then Close.
Close·Your playbookv3 · draft
05Assistant reads
How you run

Refunds, deposits, and changes — in your words. Your assistants quote these directly.

Refunds
30 days
Full refund up to 30 days before the start date
Deposit
30%
Holds your place · balance due 30 days before
Draft from what you just told us — Save to Brain to confirm
Save to Brain
Teach your Brainadd · change · remove
(1c) Close — the takeover lifts and she is back on the SAME Connect tab she triggered from, Policies already re-read. Saved here, so it is a plain ✓ Confirmed row. Cropped to the module.
On-Brand Support
Connect · 03 Brain Check
From your Brain — nothing to re-type
Questions and policies
✓Questions · 14 items
Confirmed
Edit in Brain →
Branding 0 of 1
⚠Brand voice
Needs review — last confirmed Jun 12
Review in Brain →
How you run 1 of 1
✓Policies
Confirmed · just now
Edit in Brain →
4 sections ready ✓show all
6 of 7 ready — 1 needs you before it answers guests
Try reads this same check back as one line — it never re-asks.
(2) Connects destination — same mechanic, anchored at the app row that opened it
Connects · Messaging
WhatsApp Business

Reconnect to keep replies going out from this number.

Meta login opens in a popup
Continue with WhatsApp

◄ tap the peek edge to go back — your setup is untouched

On-Brand Support
Connect · 01 Connect apps
01 · Connect apps
Communication WhatsApp Business
Where your guests already message you
Being fixed on the left — this row updates the moment it's back
Reconnecting…
AI Model MystFlo AI
Writes the replies in your voice. AI runs on MystFlo — paid per run, no key to set up.
Connected ⌄
(3) Funds destination — tap the balance, Top up slides in (amount + card chip). Not Billing.
Wallet · Top up
Top up

Runs draw from this. Nothing else is charged.

Amount
●$25
○$50
○$100
○$200
○Custom
Visa ···4242The card this top-up charges — tap to change Change →
Add $25.00

◄ tap the peek edge to go back — your setup is untouched

On-Brand Support
Connect · 02 Wallet
02 · Wallet
Wallet balanceBeing topped up on the left — this row updates the moment it's back $0.00

Connect still has no Billing link. The only setup path into Billing is the card chip on Top up. Same slide mechanic, same host — the pane swaps destination.

(4) Change card — tapped Visa ···4242 on Top up; Billing slides in at the card block
Billing · Card
Payment method

The card Top up will charge. Invoices and usage stay on Billing — not on Connect.

Visa ···4242Default · expires 08/28 Default
Replace this card
Card number
Expiry
MM / YY
CVC
123
Save card

◄ tap the peek edge to go back to Top up — Connect never opened Billing

On-Brand Support
Connect · 02 Wallet
02 · Wallet
Wallet balanceStill $0.00 — topping up waits until the card is saved $0.00
R35 — Three destinations, one mechanic funds-first 2026-08-18

One component (`PageSlideOver`, `modalTokens.slide.split.*`), same 0.45s expo settle, same peek-edge/Esc return:

Connect-tab rowLeft pane opensAnchored at
01 Apps (Reconnect / first connect)Connects pagethat app's row
02 Funds (tap the balance)Top-up paneamount + card chip
Card chip on Top-upBilling pagethe card / payment-method block
03 Brain (Add/Edit in Brain)Brain pagethat section
  • 2026-09-10 amendment (#4714, Peyton): from the Brain Check rows (wizard Connect + the assistant detail sheet) destination (1) is the REAL /brain/book with the Teach bar — drawn at 5d.
  • 2026-09-12 amendment (Peyton, on the design preview) — supersedes the clause above. The 09-10 bullet had kept the focusSection co-edit form in this frame's left pane "for the mechanic," retiring it from the 5d door only. Peyton reviewed the preview and ruled the distinction doesn't hold: when the user clicks Add to Brain it should not open that left-side field panel — it should open the designed playbook with the Teach bar. Destination (1) above is now redrawn as the Book, so this frame no longer contradicts 5d or the shipped behaviour (AC-BRAIN-213 ↗). The co-edit form remains drawn only where 14b / 14d still show it — each still owed its own re-rule, and neither is a Brain-Check door.
  • (a) Reconnect always routes through the Connects pane — nested `ConnectionModal` (PR #2154) retired on this path, stays for small confirms elsewhere.
  • (b) Connect never opens Billing. Tap funds → Top-up pane (amount presets + confirm + card chip). Billing slides in only from that chip, for card change. Dropped: “Top up stacked over the Billing pane.”
  • (c) Live-row-update promise per destination: apps “…it's back”, funds “…topped up”, Brain “…you save”.
  • (d) Mobile 375: no split on any destination — full-screen push with peek-edge return, one pattern for Apps, Top-up, Change card, and Brain.
D-1 · R20 — Brain destination amended 2026-09-12 — the pane is the Book, not a co-edit form
  • Only entry is Connect (Personalize has no Brain Check rows); opens at its own section, never the top of the Brain — this remains the correct intent and is unchanged.
  • What that section looks like, amended 2026-09-12 (Peyton 2026-09-10 / 2026-09-12): it is the real designed playbook (the Book) with the Teach bar docked — the Ink & Air chapter that owns the gap, landed directly (chapter 05 How you run in the frame above, because the row being added is Policies). It is not the focusSection co-edit field panel this frame used to draw. Correcting a fact is one mechanic everywhere: tap the bar → the peek → type → Read. A founder never meets a form she has not seen before on this path.
  • Amended 2026-09-12 (Peyton — "takeover for now"): there is no right pane on this destination. The Book covers the screen, so the row has already re-read when she returns — she teaches, sees the chapter update in her own book, hits Close, and lands on the SAME tab she triggered from with the row updated (✓ Confirmed, or the draft state if she closed before saving — team-lead correction 2026-09-10). Watching the row flip live, side by side, is a considered wave-2 option, not a retired one — it needs the split geometry back, which this ruling defers; revisit it with the wave-2 corrections[] contract (#4715).
Build
  • Host sheet re-insets left 0→40%, drops reveal gap, squares radius on 0.45s expo — never slides by transform. Below the split breakpoint: full-screen page with peek-edge back. Tokens: `modalTokens.slide`.
  • Apps / Top-up / Brain all route through `PageSlideOver`, never a bespoke modal; `ConnectionModal` never renders on the Reconnect-from-Connect-tab path. Top-up IS the pane (amount + card chip), never a sheet stacked on Billing. Billing is a second slide, only from that chip.

Spec: modal-slide-choreography-architecture.md.

Frame 14 draws the split at rest. These are the moments between “she taps Connect” and “she's back on her row”, plus the tier the split doesn't engage at. Drawn on the Connects destination — it is the only one of the destinations that can leave the tab — but loading, error, settle and abandon are mechanic-level and read identically for Top-up, Change card, and Brain.

Two rulings run through every frame below. ① The geometry does not mirror for Connect. LEFT 40% stays the real page, RIGHT 60% stays the host wizard — the 2026-07-26 axis lock holds here with no Connect-specific exception (reasoning in the design notes). ② The connect form IS the pane's content, never a sheet inside it. The pane opens already focused on the app the row named; there is no directory to walk back through and no second overlay.

768 · below the split's engage point — the destination is a full-screen push, not a narrow split
◄ Waitlist + Launch · Connect — tap to return
Connects · Email
Resend

Sends your launch emails from your own address.

API key * required
Paste your Resend API key…
Connect Resend

You'll land back on Connect with this row ticked.

The split engages at ≥1024 only (modalTokens.slide.split.engageBreakpoint) — so 768–1023 gets the same push 375 does. This is the right answer, not a shortfall: 40/60 of a 1024 viewport is 410/614, and a 614px host pane falls below the 640px stack boundary the Connect rows just locked (AC-CONN3-04 ↗) — every row would restack while she's away, so the surface she returns to isn't the one she left. The push freezes the wizard exactly as it was. Wording correction to R35 note (d): it reads “Mobile 375: no split on any destination” — the real rule is below 1024, on every tier, and 375 is only its narrowest sample. Scope: this rules the R35 destination split only; the separate open question about the Personalize preview split at 768–1023 (activation PRD, flagged 2026-07-24) is a different surface and is NOT decided here.

(4) LOADING — the pane opens instantly and already knows the app; only the provider's own form waits
Connects · Email
Resend
 
 

◄ tap the peek edge to go back — your setup is untouched

Waitlist + Launch
Connect · 01 Connect apps
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Connect
Storage Google Sheets ▾
Where your signups land
Connected ⌄
(5) ERROR — the key was rejected; the failure lives in the pane, at the field that caused it
Connects · Email
Resend

Sends your launch emails from your own address.

API key * required
re_••••••••••••3f2a

Resend didn't accept that key. Copy it again from Resend — it starts with re_ and has no spaces.

Try again

◄ tap the peek edge to go back — your setup is untouched

Waitlist + Launch
Connect · 01 Connect apps
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend isn't connected yet — connect it to send launch emails
Connect
Storage Google Sheets ▾
Where your signups land
Connected ⌄
(6) SETTLE — job done: the pane holds the tick for a beat, then closes itself; the row lands Connected
Connects · Email
✓Resend connected

Launch emails will send from your own address.

◄ taking you back to Connect…

Waitlist + Launch
Connect · 01 Connect apps
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend connected — both channels are ready
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄
(6b) SETTLE, job NOT done — the provider hands back a second choice, so the pane stays open
Connects · Storage
✓Google connected

One more thing — where should the signups land?

Google Sheet
◉Create a new one
We make a new sheet in your Drive with the template
○Link a sheet I already have
We add a new tab — we never touch your existing tabs
Use this sheet
Waitlist + Launch
Connect · 01 Connect apps
01 · Connect apps
Storage Google Sheets ▾
Where your signups land
Nearly there — finish choosing on the left
Connecting…
(7) ABANDON — peek edge tapped after submit: the pane is gone, the connection is NOT cancelled, the row finishes alone
Waitlist + Launch
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run
✕
Overview› Personalize › Connect› Try
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend is still connecting — this row updates on its own
Connecting…
Storage Google Sheets ▾
Where your signups land
Connected ⌄
02 · Wallet
Wallet balanceEach run draws $0.25 from your prepaid balance $41.20 →
03 · Brain Check
5 of 5 ready ✓ — untouchedshow all
Leaving the pane changed nothing here — closing it is navigation, not cancelling.
(8) OAUTH RETURN — fresh tab, fresh history: the wizard reopens from its own 24h draft, on Connect, row already ticked
Waitlist + Launch
A signup page and launch blast for your next cohort — built from your Brain.
$0.25 per run
✕
Overview› Personalize › Connect› Try
Resuming where you left offYour answers from Personalize are exactly as you left them.
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend connected while you were away
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄
02 · Wallet
Wallet balanceEach run draws $0.25 from your prepaid balance $41.20 →
03 · Brain Check
5 of 5 ready ✓show all
No pane reopens — the job it was opened for is done.
Story
  • She pastes the wrong key at 11pm. The red line sits under the field she typed in, not on a row across the screen, and says the two things that actually fix it — where to copy it from, and what it should look like.
  • She taps Connect on WhatsApp, Meta throws her into its own login, and she comes back three minutes later to a fresh tab. The wizard is open on Connect, her Personalize answers are exactly where she left them, and the row she tapped is already green. She never presses a “continue” button to get her own work back.
Acceptance cites existing ACs only — this file mints none
  • The R35 split engages at ≥1024 on every destination; 768–1023 and below get the full-screen push with peek-edge return. Below 1024 the host wizard is never re-laid-out mid-flow, so its Connect rows never cross their own stack boundary while she's away — AC-CONN3-04 ↗ · NEW (PRD debt · R35 tier gap).
  • The pane opens with the app's identity already rendered (eyebrow + name, from the row that opened it) and skeletons only the provider's own form; there is never an empty pane, and never a spinner over both panes — shipped.
  • A connect failure renders in the pane, attached to the input that caused it. The host row reverts to its unconnected state with the copy it already carries (“Resend isn't connected yet — connect it to send launch emails”) and white Connect — never a red the founder can't act on from the right — AC-CONN3-01 ↗ · shipped.
  • A dismissed provider popup is NOT a failure: the pane stays on its form, unchanged, with no message. Only a provider-returned denial or rejection renders an error — shipped.
  • On success the pane holds its tick ~600ms and then the HOST closes the split (the pane never self-dismisses into a state its opener doesn't know about). The pane STAYS OPEN when the provider hands back a further choice (Google's sheet pick, WhatsApp's number pick) — auto-close fires on job done, not on connection succeeded — shipped.
  • Closing the pane is navigation, never cancellation. Nothing submitted → nothing saved, no confirm dialog, the typed secret is discarded. Already submitted → the request completes and the row updates on its own (R35 note c). While a provider popup is open the peek edge is inert and the pane says so — shipped.
  • After a full-tab OAuth round trip the founder lands back INSIDE the wizard on the Connect tab with step/configuration/terms restored from the 24h draft and the existing “Resuming where you left off” line — AC-ACTIVATION-07 ↗. The co-edit pane does NOT reopen. The shipped “Ready to activate → Continue Activation” banner on the standalone Connects page demotes to the FALLBACK for when the draft can't be reopened — shipped.
  • The connect form renders as the pane's own content, not as a nested sheet inside the pane. PaneScopeContext containment stays for genuinely secondary asks raised from inside a pane (a permission prompt, a resource picker overlay) — AC-PANE-01 ↗ · AC-PANE-03 ↗.
Design notes
  • Ruling A — the axis does NOT mirror for Connect, and this is not an exception, it's the rule holding. The objection is real: her typing sits in the 40% and the passive host takes 60%. Three things beat it. ① Width isn't the problem. 40% of 1180 is 472px of pane, ~432px of content — wider than the 375 push where the identical form already reads fine. A one-field API key form and a single “Continue with WhatsApp” button do not want 700px. ② The 60% is where the density actually is — five role rows with badges, sub-lines, status buttons, plus the Brain Check rail. Mirroring squeezes THAT to 472px, which drops it under the 640px stack boundary (AC-CONN3-04 ↗): she'd leave an inline list and return to a stacked one, breaking the pane's own promise that “your setup is untouched.” ③ The uniform axis is the product. The 2026-07-26 lock retracted a mirrored draft precisely so founders never relearn which side is which; a Connect-only reversal buys ~240px and costs the one mechanic, three destinations promise. Flagged, not changed: that lock's parentheticals gloss LEFT as “the surface you're already on” and RIGHT as “the destination content” — true for Brain's detail-sheet split, backwards for R35, where the destination is what slid in. The geometry is right; the gloss needs a wording fix in the kit (LEFT 40% = the real page · RIGHT 60% = the task surface), not a geometry change.
  • Ruling B — the form is the pane, not a sheet in the pane. R35's whole claim is “the real page slides in as the REAL page, never a nested modal.” A modal inside that page is two overlays doing one job — the exact species duplication section 5b just spent a pass deleting from the Connect row. Concretely a sheet inside a 472px pane fills it edge to edge anyway, so it buys no space and costs a second backdrop and a second “back” (its ✕ lands on a directory; the peek edge lands on the wizard) — two backs in one column is the defect. So the pane opens focused: the wizard already named the app, and making her find it again in a Connects directory is the “never asked twice” rule broken. Named cost, and it is the biggest one in the item: ConnectionModal's body must become a form component the Connects page can render inline, and ConnectsPage needs a focus prop + masthead strip in the same shape BrainPage.focusSection / TeamPage.focusTab already use. That is a component extraction, not a new overlay mode.
  • The host row's four-state ladder — and a copy conflation this fixes. Pane opens → row anchored, button UNCHANGED (Connect). The highlight is the signal — no spatial “on the left” line. Submit fires → Connecting…. Success → Connected ⌄ + a transient emerald line that clears. Failure → back to Connect + the warn line. Frame 14's existing frames label the pane-open moment Connecting… / Reconnecting… — that verb belongs to the post-submit state; at pane-open nothing is connecting yet. Same correction applies to destination (2)'s Reconnecting….
  • Emerald here is a confirmation tick, not a new status colour (C12). It is transient — the row settles back to plain Connected ⌄; a permanent green line would become another thing to skip.
  • Why no “discard your changes?” confirm on abandon. A confirm dialog earns its interruption when the work behind it is expensive. An unsubmitted API key is a re-paste; a confirm makes leaving feel dangerous when it isn't. And the typed value is deliberately NOT retained across the close — keeping a secret alive longer than the surface that asked for it is a cost with no matching benefit.
  • The inert peek edge while a provider popup is open is a build constraint made honest, not a preference. Meta/Google popups call back into the page that opened them; unmounting the pane mid-popup strands the callback. Blocking the return for those seconds — with the pane saying to finish or close the provider window — is the smaller cost. The better long-term fix is hoisting the callback above the pane so the return is never blocked; that's an upgrade, not a launch requirement.
  • What the OAuth return needs that doesn't exist yet: the wizard's 24h draft already carries step, tab, configuration, terms and pricing per template, so her config genuinely survives today. What is NOT stored is the pane's own coordinates — which row, which app. That is one small stash ({templateId, role, app}) alongside the sessionStorage bridge the Connects page already keeps for the auth round trip, and the return URL already has the parameter that reopens the wizard.
Left open — deliberately not invented needs a ruling before build
  • Draft expired, or she returns on a different device. The connection IS made server-side, but the wizard's place is gone — there is no draft to reopen and no “where was I” to restore. Today's “Ready to activate → Continue Activation” banner covers the same-device case only. The cross-device case has no answer in the shipped code and none is drawn here.
  • Whether the pane should reopen after an OAuth return that landed a further choice (Google connected, sheet not yet picked). The settle rule says the pane stays while the job isn't done — but after a full-tab round trip there is no pane to stay. Reopening one contradicts frame 8; not reopening leaves a half-done Storage row. Both readings are defensible, so neither is drawn.

Components: PageSlideOver.tsx (page: 'connects' shipped) · ConnectsPage.tsx (embedded + focusProvider + masthead strip shipped) · ConnectionModal.tsx (body extracted to an inline form) · PaneScopeContext.tsx (shipped #2248 — containment already works). Spec: modal-slide-choreography-architecture.md §1. Kit: design-decisions.md 2026-06-23 + 2026-07-26.

Wallet ran dry on a chat assistant. Target behaviour (#4522, not shipped): for 15 days her customers still reach her on Slack; after that nothing is relayed and nothing is sent to the customer — the only signal is in-app, until she tops up. Three surfaces that already show the pause each get one honest line — the status line, badge and colour do not change (D-3).

Day 3 · grace — Pulse Overview · View issue → sheet
Pulse
OverviewActivePastRuns
Runs this week
142
588 this month
Cost MTD
$48.20
$0.35 per run
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue →
Breakdown
Deposit chaserDeposit Chaser · ASST-5T3Paused — needs you
Autumn retreat supportOn-Brand Support · ASST-7Q1Active
Issue✕
PausedDeposit chaser ASST-5T3
Paused — wallet empty
Replies are paused. New messages still come to you on Slack to answer yourself — for 12 more days.
Day 3 of 15 · until Sep 18
After Sep 18, new messages stop coming through to you. Top up any time and everything resumes.
Paused Sep 3
Add funds
Day 16 · stepped down — same door, the lead changes
Pulse
OverviewActivePastRuns
Runs this week
142
588 this month
Cost MTD
$48.20
$0.35 per run
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue →
Breakdown
Deposit chaserDeposit Chaser · ASST-5T3Paused — needs you
Autumn retreat supportOn-Brand Support · ASST-7Q1Active
Issue✕
PausedDeposit chaser ASST-5T3
Paused — new messages no longer reach you
The wallet has been empty for 15 days, so messages stopped coming to you on Slack. Nothing gets answered until you top up.
Top up any time — replies and Slack alerts pick up the moment it lands.
Paused Sep 3 · stopped reaching you Sep 18
Add funds
Pulse wall cards — the footer caption carries the state · three-up at 1180
Day 3 · grace
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
Messages still reach you · 12 days leftTop up →
Day 16 · stepped down
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
New messages no longer reach youTop up →
Reference · today (#4516) — non-chat / payment_failure keep this
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
Nothing lostTop up →
8e — Wallet-empty grace window · what this frame locks LOCKED by Peyton 2026-09-06 — caption carries the countdown · no customer-facing text in either state · chat assistants only · NOT built · needs #4522
  • User story. Her wallet ran dry on a chat assistant. For 15 days her customers’ messages still reach her on Slack to answer herself — TARGET behaviour, built by #4522, not what happens today (today only the FIRST message of a wallet-empty pause relays; later ones go nowhere — no Slack, no customer hold note); after day 15 nothing is relayed and nothing is sent to the customer — the only signal is founder-facing, in-app, on the assistant — until she tops up, which resumes everything instantly. No bot text reaches the customer in either state (Peyton 2026-09-06): the grace relay is silent + her own manual reply, exactly like human-mode today. She needs to see what is still working, how many days are left, and what changed once it stops.
  • Acceptance. AC-PULSE-19 ↗ (the wallet row sits in Band A with View issue) · NEW (PRD debt): the issue sheet names the runway in days while relaying · NEW (PRD debt): the issue sheet lead changes once relaying stops; no customer-facing message exists in either state · NEW (PRD debt): the post-card footer caption carries the same two states on chat assistants only · NEW (PRD debt): the day count is derived from ONE backend clock, never a client guess.
  • Where it lives. The issue sheet (View issue → same RunIssueSheet as pulse.html 4b) is the ONE detail surface — the 2026-08-22 “one attention pattern” lock stands, so the Needs-attention ROW is unchanged. The card footer caption is the glance signal on the wall. The Connect-tab wallet notice sub-line echoes the same state. Nothing new is invented: three surfaces that already show the pause get one more honest line each.
  • Amber stays amber, both states. D-3’s rule text reserves red for “something broke and you may have lost work”. Day 16 is still a 30-second top-up that resumes everything, and the assistant is Paused, not Failed — so the badge, dot, and the verbatim status line “Wallet empty — top up to keep running” do not change. Severity is carried by copy (lead + caption), never by a new colour or a new badge word.
  • Calm, not alarm. No countdown in red, no exclamation, no “urgent”. The runway is a quiet hairline track + Day 3 of 15: determinate progress per U13, static (no motion — nothing is running).
State machine — TARGET, not shipped every transition below is built by #4522 (chief-cto spec); today’s code has no grace window and no relay after the first message
   top-up lands (any time) ─────────────────────────────────────────────┐
                                                                        ▼
┌───────────┐  wallet can't   ┌──────────────────────┐  day 15   ┌──────────────────────┐
│  Active   │ ─cover a reply─►│  Paused · wallet_empty│ ─────────►│  Paused · wallet_empty│
│  (chat)   │                 │  GRACE  · relaying    │           │  STEPPED · not relaying│
└───────────┘                 │  Slack ◄─ every msg*  │           │  customer ◄─ nothing  │
      ▲                       │  card: “12 days left” │           │  card: “no longer     │
      │                       │  sheet: runway + next │           │        reach you”     │
      └────── resumes ────────┴──────────────────────┴───────────┴──────────────────────┘
   * TARGET (#4522). Shipped today: first message relays, every later one during the pause is dropped.
Copy — exact strings chat assistants · wallet_empty only · payment_failure keeps today’s copy · every line is founder-facing — nothing here is ever sent to a customer
SurfaceGrace (day 1–15)Stepped down (day 16+)
Card status lineWallet empty — top up to keep running (D-3 verbatim, unchanged)same — unchanged
Card footer captionMessages still reach you · 12 days leftNew messages no longer reach you
Card actionTop up →Top up →
Attention rowWallet empty — top up to keep running · View issue (unchanged)same — unchanged
Sheet badgeamber Paused (today’s sheet hardcodes red Error — build finding)amber Paused
Sheet leadPaused — wallet emptyPaused — new messages no longer reach you
Sheet whyReplies are paused. New messages still come to you on Slack to answer yourself — for 12 more days.The wallet has been empty for 15 days, so messages stopped coming to you on Slack. Nothing gets answered until you top up.
Sheet runwayDay 3 of 15 · until Sep 18—
Sheet nextAfter Sep 18, new messages stop coming through to you. Top up any time and everything resumes.Top up any time — replies and Slack alerts pick up the moment it lands.
Sheet timePaused Sep 3Paused Sep 3 · stopped reaching you Sep 18
Sheet CTAAdd fundsAdd funds
Connect notice sub-linePaused until you add credit — it resumes the moment your top-up lands. Messages still reach you on Slack for 12 more days.Paused until you add credit — it resumes the moment your top-up lands. New messages no longer reach you until you do.
  • Day-count grammar: “for N more days” (N ≥ 2) · “for 1 more day” · “until the end of today” (N = 0). Caption: “N days left” · “1 day left” · “last day”. Never “0 days”.
  • Caption fit rule: the caption is one line, truncate. If “Messages still reach you · 12 days left” cannot fit beside “Top up →” at the card’s width, render the day-count clause alone (“12 days left”) — the number is the part that must survive, never the prose.
  • “Nothing lost” stays for non-chat assistants and for payment_failure (the #4516 shared branch) — this caption is a third branch keyed on chat runtime + wallet_empty, exactly the split the D-3 amendment already anticipated.
Data this design needs dependency on chief-cto’s backend spec (#4522) — design does not block on it; copy must not ship before it
  • Gate: none of this copy goes live before #4522 ships. Every line above describes the TARGET relay behaviour. Until the 15-day relay is real, the honest live copy stays what #4516 shipped (“Nothing lost” caption, “Wallet empty — add funds to keep running.” sheet) — a caption that says “Messages still reach you” on today’s code would be false from the second message on.
  • Grace end (one clock). A backend-owned grace_ends_at (or the pause timestamp the step-down cron reads + the 15-day constant). Pulse already carries last_paused_at (“Status since”), so the day count is derivable client-side today — but only if the step-down job uses the SAME timestamp, otherwise the sheet says “1 day left” while the cron already stopped relaying. Prefer the backend exposing the end date over the client re-deriving it.
  • Relay state (explicit, not inferred). A field that says relaying / stopped — a sub-state on the pause, or a distinct pause_reason value. The UI must never infer “stopped” from “today > day 15”: the two would drift by a cron tick and the founder would read the wrong sentence. If it is a new pause_reason, the D-3 resolver maps it to the SAME amber Paused + verbatim line (no new colour, no new badge word).
  • Chat runtime flag on the post card. The caption branch keys on flowPattern.runtime === 'chat'; confirm the post card / Pulse stats already carry it (it decides whether “Messages still reach you” is even true — a platform-triggered assistant has no customer messages to relay).
  • Optional, later: a count of customer messages that arrived while stepped down. If the backend stores them, the stepped sheet can add “N messages arrived while paused” — a real reason to top up. Not drawn; not required.
  • Email touchpoint (out of this frame): the existing wallet_empty_paused daily reminder should carry the same day count and the same day-15 change. Copy owner: chief-writer; mechanism: chief-cto.
Build findings on the shipped surfaces not fixed in this design-only round
  • RunIssueSheet.tsx renders a red Error badge for every caller, including wallet / budget pauses — contradicts D-3 (amber for a retryable wallet state, red for Failed only). The sheet should take the badge from the owning rule: amber Paused for wallet / limit / setup pauses, red Error for a failed run, lantern Needs attention for a chat leftover (pulse.html 1q already draws that).
  • ConnectWalletFunds.tsx paused sub-line “top up to resume it yourself” is stale for wallet_empty since #4496 (top-up auto-resumes). Keep it for payment_failure; wallet_empty reads “it resumes the moment your top-up lands.”
  • Tier rule (U8): the sheet is the same content column at every width — 375 edge-to-edge bottom sheet, 768 and 1180 a full-width band with the prose column capped at 720 (contentWidth="prose"). Cards: 375 one column, 768 two-up, 1180 three-up, caption rule identical. No per-state tablet frame is owed — the rule covers states not yet drawn.
9c · 9g — 768Post detail sheet — header + Personalize locked mirror at tablet REDRAWN 2026-09-04, same day · #4432
768 · ACTIVE — same four-line header, mirror fills the 720 measure
tablet 768 — seated sheet, gutter 24 (sheet chrome token)
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Pulse Overview Personalize Connect

This is what's set for this round — nothing here can be edited in place. To change any of it, start fresh with a new assistant → (the ⋯ menu, top right). Brain readiness lives on Connect →

01 · Your workshop
Workshop name
Saturday Sound Bath Workshop
Workshop date
Sat Feb 9, 2026 · 11:00
Price per seat
USD45
Total seats
12
03b · Where guests book
In this chat
WhatsApp's own tap-through form.
Your own booking form
Bookings land in your sheet, you tick paid there.
04a · Booking messages
Payment ask
Your seat is held — it's confirmed the moment your payment lands.
Booking confirmation locked
Meta-approved · not editable
You're booked, Maya — see you Feb 9 at 11:00.
03a · Where guests reach you
Booking link
wa.me/15551234567?text=book

Runs on demand — whenever a guest messages this number.

768 is a sample of the U8 continuum between 375 and 1180, not a third layout: the four header lines, the context line, and the .field-label/.field/.opt-radio rows are identical to desktop 9c/9g; only the measure changes (24px gutter, form spans the sheet). Paused / empty-field states at 768 are the desktop crops at this measure — not redrawn (Paused is byte-identical body to Active regardless of tier). The rest of the live flow at 768 stays as it was: not yet drawn — desktop and 375 are the contract.

8e — 768Wallet-empty grace window — issue sheet at tablet locked 2026-09-06 · not built · needs #4522 view at 375 ↑↓
768 · Day 3 · grace — full-width band, prose column capped at 720
tablet 768 — Pulse Overview under a soft dim, sheet rises to content height
Pulse
OverviewActivePastRuns
Runs this week
142
588 this month
Cost MTD
$48.20
$0.35 per run
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue →
Breakdown
Deposit chaserDeposit Chaser · ASST-5T3Paused — needs you
Autumn retreat supportOn-Brand Support · ASST-7Q1Active
Issue✕
PausedDeposit chaser ASST-5T3
Paused — wallet empty
Replies are paused. New messages still come to you on Slack to answer yourself — for 12 more days.
Day 3 of 15 · until Sep 18
After Sep 18, new messages stop coming through to you. Top up any time and everything resumes.
Paused Sep 3
Add funds

768 is a rule, not a third layout (U8). The sheet is the same content column at every width — 375 edge-to-edge, 768 and 1180 a full-width band with the prose capped at 720 (contentWidth="prose", sheetHeight="content", softBackdrop). The stepped-down sheet at 768 is the 375 drawing at this measure; the Pulse wall is two cards up with the identical caption rule; the Connect-tab notice is the 375 drawing inside the seated sheet at gutter 24. One drawing here so the band + column are seen once; every other 8e state inherits it.

§4 · Live
8Pulse — the seven post cards, one geometry R13 · R14 · R15 · R16
Active
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
Paused — by you (neutral)
Paused ▶⏸⏹ Details →
Spring retreat booking ASST-2K9
Retreat Booking
Paused by you · Jul 18
Runs
61 · 98% healthy · 4d ago · $21.35
Nothing lostResume →
Paused — system (amber) · ONE drawing, reason line names it
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
Nothing lostTop up →
Active — launch pending (partially active)
Active ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
Launch message with WhatsApp for approvalⓘ
Runs
18 · 100% healthy · 6m ago · $4.50
Failed (red — true errors only)
Failed ▶⏸⏹ Details →
Listing writer ASST-9M2
Product Listing Generator
Your sheet is missing the “Price” columnⓘ
Runs
37 · 81% healthy · 1d ago · $9.25
Last 6 runs failedFix the sheet →
Stopped (neutral)
Stopped ▶⏸⏹ Details →
Summer retreat support ASST-1H6
On-Brand Support
Stopped by you Jun 30 · setup saved
Runs
204 · 97% healthy · Jun 30 · $61.20 total
Your setup is savedReactivate →
Completed (neutral)
Completed ▶⏸⏹ Details →
June cohort waitlist ASST-3D4
Waitlist + Launch
Finished its job Jun 12 · 214 signups · Reactivated once
Runs
231 · 99% healthy · Jun 12 · $57.75 total
Nothing's overwrittenReactivate →
375 · Pulse list — same cards, full-bleed column
LivePausedPastAll
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
Nothing lostTop up →
R24 · post chip inversion — healthy collapses to one line
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
R24 · one connection broke — that chip IS the story
Paused ▶⏸⏹ Details →
Spring retreat booking ASST-2K9
Retreat Booking
Google Sheets · Reconnect 4 connected
Runs
61 · 98% healthy · 4d ago · $21.35
Resumes once it's backReconnect →
R24 · waiting on the provider — verb is Pending, never Verify
Active ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
WhatsApp Business · Pending 3 connected
Runs
18 · 100% healthy · 6m ago · $4.50
Records assistant — the Attendees line is a SLOT IN the card not built · 2026-09-02
Active ▶⏸⏹ Details →
October pottery weekend ASST-9W2
Workshop Booking · $1.75 per booking
1 connected · next session Sat 10:00
Runs
31 · 100% healthy · 2h ago · $14.00
Attendeeswho's coming, who still owes you19 booked · 5 left ›
Sold out — amber dot, monochrome row
Active ▶⏸⏹ Details →
Spring retreat ASST-2K9
Retreat Booking · $1.75 per booking
2 connected
Runs
61 · 98% healthy · 4d ago · $21.35
Attendeeswho's coming, who still owes yousold out · 2 waiting ›
Non-records assistant — slot collapsed, card unchanged
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support · $0.50 per session
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
R36 — Records slot IN the card Peyton 2026-09-02 · supersedes the under-card RecordsEntryRow
  • Last zone of the fixed map, after Runs, before the footer action: noun · sub-label · "N booked · M left ›"; sold out = amber dot + "sold out · N waiting". Collapses to zero height on a non-records card (no reserved band — 2026-07-23 precedent). Never renders for guests. Tap → detail sheet on Pulse + records sheet (9e-m). Desktop pair: frame 8d.
R16 — Seven cards
  • Active · Paused by-you (neutral) · Paused system (amber, one drawing for wallet/budget/schema, reason line names which) · Active–launch pending (amber meta) · Failed (red) · Stopped (neutral) · Completed (neutral).
  • Template rejected is frame 7(e), referenced from the legend (8b).
R13 · A4 · R14 · D4 — Geometry + identity
  • Fixed zone map, same on every card (frames 1, 2, 8): badge+controls → title (instance name + id) → identity sub-line (template name alone) → status-message line (reserved, min-height) → hairline (≥12px air both sides) → Runs row → footer action pinned bottom.
A5 — Control row
  • ▶ ⏸ ⏹ always in that order; inapplicable ones stay `.off` (dim, no hover), never omitted — Active: ▶ off; Paused/Failed: ⏸ off; Stopped/Completed: ⏸+⏹ off.
  • Labeled footer action (“Resume →” / “Fix the sheet →” / “Reactivate →”) stays the primary doorway (D-4); icon row is secondary.
R15 · R24 · D3 — Chips + wallet
  • Max 3 chips + `+N`, one meta line, no benefits on a card.
  • Post-activation inverts: unhealthy-only chips + “N connected” quiet line; verbs Reconnect/Pending only, never a cost signal.
  • “Payment” retired — `payment_failure` reads amber “Wallet empty — top up to keep running”; only terminal account failure earns red.

Archetypes: assistant-summary-card.md, pulse-surface.md.

8bStatus ladder — the whole legend on one screen D3
What each status means
Colour is an exception, never decoration. Most of your assistants are neutral.
Active Working. Neutral chip, emerald dot. The dot is the only colour — status is a dot (shell-language #4).
Active meta amber Active — launch pending. Replies and signups are live; one outbound piece waits on WhatsApp. Amber lives on the meta line, never the badge — the card must not read “nothing works”.
Active + pending row Active — waiting on you (R31, frame 12). The assistant has handed a step back: send the launch, publish the listings, open the next cohort. Still Active, still emerald — the badge does not change, because nothing is broken and the assistant is still working. The “Waiting on you” row is a flag on the card, not a status. ONE per assistant.
Paused Paused by you. Neutral. You did it on purpose, so nothing shouts.
Paused Paused by us — needs you. ONE word, amber, for every system pause: wallet empty, budget line reached, sheet changed shape. The reason line names which. Wallet copy: “Wallet empty — top up to keep running.”
Failed Something actually broke. Red is reserved for true errors and terminal account-level failure. A state a top-up fixes in ten seconds never earns red.
Failed Template rejected (frame 7e) — red family, always with a named fix path. Never a dead end.
Stopped Off, setup saved. Neutral. Lives in Past. CTA: Reactivate →
Completed Finished its job. Neutral. Lives in Past. CTA: Reactivate →
What each status means
Active
Working. Neutral chip, emerald dot.
Active
Launch pending. Amber on the meta line only — replies already work.
Active
Waiting on you. Still Active — a “Waiting on you” row on the card, never a new badge (R31).
Paused
By you. Neutral.
Paused
By us — needs you. Wallet, budget, or a changed sheet. The reason line says which.
Failed
Actually broke. True errors only.
Stopped
Off, setup saved. Reactivate →
Completed
Finished its job. Reactivate →
D3 — Status ladder LOCKED 2026-07-23
  • Single source the `assistantStatus.ts` resolver builds against. Amends the 2026-07-05 severity map: “Payment needed” red badge → amber wallet-empty pause; red reserved for Failed.
  • Resolver sub-table: `payment_failure` (retryable) → amber Paused + “Wallet empty — top up to keep running”; `payment_failure_final` (terminal) → red Failed + named account action. No new DB status/schema change.
  • `pending_template_approval` flips on Meta's webhook (no polling); `template_rejected` maps to the red-family Failed.
Build
  • No new DB enum values; `payment_failure` never renders red; `template_rejected` and true account failures share one red badge word.

Both tiers drawn per R22. Archetype: pulse-surface.md (self-check #6).

8cNeeds your attention — one inbox, Health locked to it new · 2026-08-16
Contract frame — screenshot-match this. Health Needs you, Attention 4. Band A on top. Chat leftover is not first.
OverviewActivePastRuns
Runs this week
142
588 this month
Health
Needs you
Attention
4
Needs your attention 4
On-Brand Support
A connected app disconnected — reconnect to keep it running
Reconnect
Deposit chaser
Wallet empty — top up to keep running
View issue
Maya · 2 seats
Overdue — was due Aug 12
Mark paid
****5373
AI wasn’t sure
I handled it
Health tile — same chrome, four states. Never a %.
Inbox open, no failed runs
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
On-Brand Support
A connected app disconnected — reconnect to keep it running
Reconnect
Failed runs outrank inbox copy
OverviewActivePastRuns
Health
2 failed
Attention
1
Needs your attention 1
Listing writer
Your sheet is missing the “Price” column
Fix the sheet
Inbox empty, runs exist
OverviewActivePastRuns
Health
All good
588 runs this month
Attention
✓
Needs your attention
Nothing needs you right now.
No runs, inbox empty
OverviewActivePastRuns
Health
—
No runs yet
Attention
✓
Needs your attention
Nothing needs you right now.
Band A — assistant cannot run. Tiles locked to Needs you / 1.
Connection down
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
On-Brand Support
A connected app disconnected — reconnect to keep it running
Reconnect
Wallet empty / charge failed
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue
Budget limit
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Autumn retreat support
Budget limit reached — top up to keep running
View issue
Assistant failed
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Listing writer
Something went wrong — check details to resolve
Open
Sheet columns changed
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Listing writer
Your sheet changed — check the column setup
Fix the sheet
Meta still reviewing
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
October cohort waitlist
Launch message with WhatsApp for approval
Check review
Meta rejected
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
October cohort waitlist
WhatsApp turned down your launch message — check your email for the reason and the fix.
Fix the copy
Stopped — still needs you
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Summer retreat support
Account suspended — update payment to reactivate
View issue
Waitlist launch sitting unsent
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
October cohort waitlist
Review your list and send the launch
Review launch
Band B — one leftover. Sits under Band A. Does not block the assistant list. Never Resume AI.
Chat handoff
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
****5373
AI wasn’t sure
I handled it
Booking overdue
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Maya · 2 seats
Overdue — was due Aug 12
Mark paid · Extend · Release
Booking waiting
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Jordan · 1 seat
Due Aug 20
Mark paid
Exclude — founder chose it. Card exists. Not in the box.
Paused by you — not in inbox
OverviewActivePastRuns
Health
All good
Attention
✓
Needs your attention
Nothing needs you right now.
Paused
Spring retreat booking
Retreat Booking
Paused by you · Aug 12
Stopped by you — not in inbox
OverviewActivePastRuns
Health
All good
Attention
✓
Needs your attention
Nothing needs you right now.
Stopped
Summer retreat support
On-Brand Support
Stopped by you Jun 30 · setup saved
Job of the box
  • “Which of my assistants cannot work until I do something?” One inbox. The second “Needs attention” list under the assistant grid is gone.
  • Status-driven, not template-driven. On-Brand Support, booking, waitlist, checkout, launch kits, and future assistants inherit the same rules.
Health lock
  • Health and Attention share the inbox count. Health may never read All good or a % while the count is > 0.
  • Account Health tile = operational (Needs you / N failed / — / All good). Per-assistant 96% healthy on cards / Pulse tab / Breakdown is a different number and may stay.
  • Click either tile → #attention-panel. No #health-alerts fallback.
Band A then Band B
  • Band A (top): connection · wallet · budget · failed · sheet · Meta review/reject · stopped-needs-you · launch unsent.
  • Band B (under): chat handoff · unpaid / overdue booking. I handled it / Hand back to AI — never Resume AI. These do not block the assistant list.
  • Out: founder paused or stopped on purpose.
Build
  • PRD: prd-pl-pulse-dashboard.md §2.3 / §2.3a. Status map: prd-pl-assistant-lifecycle.md §1.2a. Two Health meanings: prd-pl-assistant-metrics.md.
  • Resolver: isAssistantNeedsAttention + resolvePulseHealth in src/lib/assistantStatus.ts. UI: AttentionPanel.tsx.

375 phones. Pulse Overview companion: pulse.html frames 1 / 1c / 1-m. Archetype: pulse-surface.md.

8eWallet-empty grace window — what she sees on day 3 vs day 16 · 375 locked 2026-09-06 · not built · needs #4522 view at 1180 ↑↓ 768 ↑↓
Issue sheet — opened from the Band A row’s View issue · same sheet as pulse.html 4b · height follows content
Day 3 · grace — messages still reach her
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue
Issue✕
PausedDeposit chaser ASST-5T3
Paused — wallet empty
Replies are paused. New messages still come to you on Slack to answer yourself — for 12 more days.
Day 3 of 15 · until Sep 18
After Sep 18, new messages stop coming through to you. Top up any time and everything resumes.
Paused Sep 3
Add funds
Day 16 · stepped down — relaying stopped
OverviewActivePastRuns
Health
Needs you
Attention
1
Needs your attention 1
Deposit chaser
Wallet empty — top up to keep running
View issue
Issue✕
PausedDeposit chaser ASST-5T3
Paused — new messages no longer reach you
The wallet has been empty for 15 days, so messages stopped coming to you on Slack. Nothing gets answered until you top up.
Top up any time — replies and Slack alerts pick up the moment it lands.
Paused Sep 3 · stopped reaching you Sep 18
Add funds
Pulse wall — the footer caption is the glance signal · status line stays D-3 verbatim
LivePausedPastAll
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
Messages still reach you · 12 days leftTop up →
Paused ▶⏸⏹ Details →
Deposit chaser ASST-5T3
Deposit Chaser
Wallet empty — top up to keep runningⓘ
Runs
88 · 94% healthy · 9h ago · $30.80
New messages no longer reach youTop up →

Two states of ONE card, stacked for comparison — a real wall never shows both for the same assistant.

Connect tab — the wallet notice sub-line echoes the same state (post-activation, isPaused)
Day 3 · grace
Deposit chaserASST-5T3
Deposit Chaser
Paused — wallet empty · $0.35 per run · live since Jul 21
✕
PulseOverviewPersonalizeConnect
02 · Wallet
Wallet balanceEach run draws $0.35 from your prepaid balance$0.00 ›
Wallet empty — top up to keep runningPaused until you add credit — it resumes the moment your top-up lands. Messages still reach you on Slack for 12 more days.
03 · Brain Check
Prices & policiesConfirmed Aug 2✓
Day 16 · stepped down
Deposit chaserASST-5T3
Deposit Chaser
Paused — wallet empty · $0.35 per run · live since Jul 21
✕
PulseOverviewPersonalizeConnect
02 · Wallet
Wallet balanceEach run draws $0.35 from your prepaid balance$0.00 ›
Wallet empty — top up to keep runningPaused until you add credit — it resumes the moment your top-up lands. New messages no longer reach you until you do.
03 · Brain Check
Prices & policiesConfirmed Aug 2✓
8e — Wallet-empty grace window · what this frame locks LOCKED by Peyton 2026-09-06 — caption carries the countdown · no customer-facing text in either state · chat assistants only · NOT built · needs #4522
  • User story. Her wallet ran dry on a chat assistant. For 15 days her customers’ messages still reach her on Slack to answer herself — TARGET behaviour, built by #4522, not what happens today (today only the FIRST message of a wallet-empty pause relays; later ones go nowhere — no Slack, no customer hold note); after day 15 nothing is relayed and nothing is sent to the customer — the only signal is founder-facing, in-app, on the assistant — until she tops up, which resumes everything instantly. No bot text reaches the customer in either state (Peyton 2026-09-06): the grace relay is silent + her own manual reply, exactly like human-mode today. She needs to see what is still working, how many days are left, and what changed once it stops.
  • Acceptance. AC-PULSE-19 ↗ (the wallet row sits in Band A with View issue) · NEW (PRD debt): the issue sheet names the runway in days while relaying · NEW (PRD debt): the issue sheet lead changes once relaying stops; no customer-facing message exists in either state · NEW (PRD debt): the post-card footer caption carries the same two states on chat assistants only · NEW (PRD debt): the day count is derived from ONE backend clock, never a client guess.
  • Where it lives. The issue sheet (View issue → same RunIssueSheet as pulse.html 4b) is the ONE detail surface — the 2026-08-22 “one attention pattern” lock stands, so the Needs-attention ROW is unchanged. The card footer caption is the glance signal on the wall. The Connect-tab wallet notice sub-line echoes the same state. Nothing new is invented: three surfaces that already show the pause get one more honest line each.
  • Amber stays amber, both states. D-3’s rule text reserves red for “something broke and you may have lost work”. Day 16 is still a 30-second top-up that resumes everything, and the assistant is Paused, not Failed — so the badge, dot, and the verbatim status line “Wallet empty — top up to keep running” do not change. Severity is carried by copy (lead + caption), never by a new colour or a new badge word.
  • Calm, not alarm. No countdown in red, no exclamation, no “urgent”. The runway is a quiet hairline track + Day 3 of 15: determinate progress per U13, static (no motion — nothing is running).
State machine — TARGET, not shipped every transition below is built by #4522 (chief-cto spec); today’s code has no grace window and no relay after the first message
   top-up lands (any time) ─────────────────────────────────────────────┐
                                                                        ▼
┌───────────┐  wallet can't   ┌──────────────────────┐  day 15   ┌──────────────────────┐
│  Active   │ ─cover a reply─►│  Paused · wallet_empty│ ─────────►│  Paused · wallet_empty│
│  (chat)   │                 │  GRACE  · relaying    │           │  STEPPED · not relaying│
└───────────┘                 │  Slack ◄─ every msg*  │           │  customer ◄─ nothing  │
      ▲                       │  card: “12 days left” │           │  card: “no longer     │
      │                       │  sheet: runway + next │           │        reach you”     │
      └────── resumes ────────┴──────────────────────┴───────────┴──────────────────────┘
   * TARGET (#4522). Shipped today: first message relays, every later one during the pause is dropped.
Copy — exact strings chat assistants · wallet_empty only · payment_failure keeps today’s copy · every line is founder-facing — nothing here is ever sent to a customer
SurfaceGrace (day 1–15)Stepped down (day 16+)
Card status lineWallet empty — top up to keep running (D-3 verbatim, unchanged)same — unchanged
Card footer captionMessages still reach you · 12 days leftNew messages no longer reach you
Card actionTop up →Top up →
Attention rowWallet empty — top up to keep running · View issue (unchanged)same — unchanged
Sheet badgeamber Paused (today’s sheet hardcodes red Error — build finding)amber Paused
Sheet leadPaused — wallet emptyPaused — new messages no longer reach you
Sheet whyReplies are paused. New messages still come to you on Slack to answer yourself — for 12 more days.The wallet has been empty for 15 days, so messages stopped coming to you on Slack. Nothing gets answered until you top up.
Sheet runwayDay 3 of 15 · until Sep 18—
Sheet nextAfter Sep 18, new messages stop coming through to you. Top up any time and everything resumes.Top up any time — replies and Slack alerts pick up the moment it lands.
Sheet timePaused Sep 3Paused Sep 3 · stopped reaching you Sep 18
Sheet CTAAdd fundsAdd funds
Connect notice sub-linePaused until you add credit — it resumes the moment your top-up lands. Messages still reach you on Slack for 12 more days.Paused until you add credit — it resumes the moment your top-up lands. New messages no longer reach you until you do.
  • Day-count grammar: “for N more days” (N ≥ 2) · “for 1 more day” · “until the end of today” (N = 0). Caption: “N days left” · “1 day left” · “last day”. Never “0 days”.
  • Caption fit rule: the caption is one line, truncate. If “Messages still reach you · 12 days left” cannot fit beside “Top up →” at the card’s width, render the day-count clause alone (“12 days left”) — the number is the part that must survive, never the prose.
  • “Nothing lost” stays for non-chat assistants and for payment_failure (the #4516 shared branch) — this caption is a third branch keyed on chat runtime + wallet_empty, exactly the split the D-3 amendment already anticipated.
Data this design needs dependency on chief-cto’s backend spec (#4522) — design does not block on it; copy must not ship before it
  • Gate: none of this copy goes live before #4522 ships. Every line above describes the TARGET relay behaviour. Until the 15-day relay is real, the honest live copy stays what #4516 shipped (“Nothing lost” caption, “Wallet empty — add funds to keep running.” sheet) — a caption that says “Messages still reach you” on today’s code would be false from the second message on.
  • Grace end (one clock). A backend-owned grace_ends_at (or the pause timestamp the step-down cron reads + the 15-day constant). Pulse already carries last_paused_at (“Status since”), so the day count is derivable client-side today — but only if the step-down job uses the SAME timestamp, otherwise the sheet says “1 day left” while the cron already stopped relaying. Prefer the backend exposing the end date over the client re-deriving it.
  • Relay state (explicit, not inferred). A field that says relaying / stopped — a sub-state on the pause, or a distinct pause_reason value. The UI must never infer “stopped” from “today > day 15”: the two would drift by a cron tick and the founder would read the wrong sentence. If it is a new pause_reason, the D-3 resolver maps it to the SAME amber Paused + verbatim line (no new colour, no new badge word).
  • Chat runtime flag on the post card. The caption branch keys on flowPattern.runtime === 'chat'; confirm the post card / Pulse stats already carry it (it decides whether “Messages still reach you” is even true — a platform-triggered assistant has no customer messages to relay).
  • Optional, later: a count of customer messages that arrived while stepped down. If the backend stores them, the stepped sheet can add “N messages arrived while paused” — a real reason to top up. Not drawn; not required.
  • Email touchpoint (out of this frame): the existing wallet_empty_paused daily reminder should carry the same day count and the same day-15 change. Copy owner: chief-writer; mechanism: chief-cto.
Build findings on the shipped surfaces not fixed in this design-only round
  • RunIssueSheet.tsx renders a red Error badge for every caller, including wallet / budget pauses — contradicts D-3 (amber for a retryable wallet state, red for Failed only). The sheet should take the badge from the owning rule: amber Paused for wallet / limit / setup pauses, red Error for a failed run, lantern Needs attention for a chat leftover (pulse.html 1q already draws that).
  • ConnectWalletFunds.tsx paused sub-line “top up to resume it yourself” is stale for wallet_empty since #4496 (top-up auto-resumes). Keep it for payment_failure; wallet_empty reads “it resumes the moment your top-up lands.”
  • Tier rule (U8): the sheet is the same content column at every width — 375 edge-to-edge bottom sheet, 768 and 1180 a full-width band with the prose column capped at 720 (contentWidth="prose"). Cards: 375 one column, 768 two-up, 1180 three-up, caption rule identical. No per-state tablet frame is owed — the rule covers states not yet drawn.
9Post detail sheet — Pulse tab (default) · 375 R30 · R17
Pulse tab — THE TEMPLATE · CHAT fill · 375 R37
dimmed Pulse peeks — tap to return
Autumn retreat support✎
On-Brand Support Assistant · ASST-7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Runs this month142
Health96%
Last run2h ago
Cost this month$18.40
Your WhatsApp chat
Guests scan or tap to message you.
https://wa.me/16318181081
WhatsAppXThreadsCopy link
MystFlo
Autumn retreat support
Scan to chat on WhatsApp
Flyer card · 2048px
Print and social · Save image
Recent activitySee all ›
24h7d30d
Session — in progress***5373 · 5 turnsjust now
Answered a guest — “is the September week still open?”$0.50 · 1.1s2h ago
Guest needs you — refund questionNeeds attentionView issue4h ago
Answered a guest — “what time does check-in start?”$0.50 · 0.8s6h ago
Reactivated — same setup, same listJul 22
This assistant’s activity.
9b twin — Pulse tab, chat fill (R37, 2026-09-03)
  • Same order as desktop 9b, single-column stack: metrics → chat share slot → activity. The old .mb band + Today/Earlier feed is retired from this frame.
  • Activity is 5 rows + See all › — no pagination bar on the tab; chips + pager live one door over in the new Activity sheet (9f-m).
Renaming — inline click-to-edit (R17)
dimmed Pulse peeks — tap to return
Autumn retreat support|
Save
Your word for this one — On-Brand Support stays the template name. ASST-7Q1
✕
Pulse Overview Personalize Connect
Runs
142
Healthy
96%
Avg Time
1.2s
Last run
2h
Spent
$18.40
Today
Answered a guest“is the September week still open?”2h ago
Waiting on you — pending item at TOP D-5
dimmed Pulse peeks — tap to return
October cohort waitlist✎
Waitlist + Launch Assistant · ASST-4B8
Active · $0.25 per run · live since Jul 21
Last run 6m ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Waiting on youSend the launch · wave 2 Review
Runs
18
Healthy
100%
Avg Time
0.8s
Last run
6m
Spent
$4.50
Today
New signup214 total · page live6m ago
Pulse tab — THE TEMPLATE · BOOKING (records) fill · 375 — roster FIRST not built · 2026-09-03
dimmed Pulse peeks — tap to return · ?assistant=4L9
Weekly wheel-throwing class✎
Workshop Booking Assistant · ASST-4L9
Active · $1.75 per run · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
Runs this month31
Health100%
Last run2h ago
Cost this month$14.00
Bookings taken this month19
AttendeesSee all 6 ›

10 seats · 7 booked · 3 left · synced 2 min ago

Aisha Kone3 seats · link sent 27 Julawaiting paymentMark paid⋯
Maya Chen2 seats · booked 26 Julpaid
Tom Reyes1 seat · booked 26 Julpaid
Devi Rao1 seat · roster tickpaid
Noor Azizjoined Aug 2waiting

5 of 6 · needs-verdict first, then newest · 2 on the waiting list

Your booking link
wa.me/15551234567
WhatsAppXThreadsCopy link
MystFlo
Weekly wheel-throwing class
Scan to book on WhatsApp
Flyer card · 2048px
Print and social · Save image
Recent activitySee all ›
24h7d30d
Booking confirmed — Priya M.$1.75 · paid6:14pm
Payment link relayed — Aisha Koneawaiting payment5:30pm
Class reminder queuedNeeds attentionView issue6:00pm
Booking confirmed — Daniel R.$1.75 · paid2:05pm
Answered a guest — “is parking included?”$0.08 · 0.9sJul 20
This assistant’s activity.
9b-r twin — Pulse tab, records fill (R37, 2026-09-03)
  • Same order as desktop 9b-r, single-column stack: metrics → roster (needs-verdict first, verdict pair on its own 44px line) → booking link/share/flyer → activity, no full-width band, no pagination bar on the tab. See all on either the roster or the activity opens the matching nested sheet full-screen (9e-m · 9f-m).
Pulse tab — THE TEMPLATE · GENERATION (kit) fill · 375 not built · 2026-09-03
dimmed Pulse peeks — tap to return
Sunrise Yoga Retreat✎ASST-M3K9
Workshop Launch Kit · active since Aug 30
✕
Pulse Overview Personalize Connect
Runs this month1
Health100%
Last runAug 30
Cost this month$3.00
Your kitOpen kit ›
Description
The short paragraph for your listing or booking page
Page copy
The full page — headline, the days, what's included, how to book
Launch blast
The email or broadcast that opens it
IG captions
Three, to post across the launch week
Flyer copy
Short-form, for print or a story card

All 5 pieces · v1 · $3.00 kit + $0.02 rewrites.

Recent activitySee all ›
24h7d30d
Kit written — v1, all 5 pieces$3.00Aug 30
IG captions rewritten — v2$0.02Aug 31
Page copy saved to DocOpen DocAug 31
This assistant’s activity.
9b-k twin — Pulse tab, kit fill (R37, 2026-09-03)
  • Same order as desktop 9b-k: metrics → piece-readiness slot + Open kit › → activity. Open kit › goes to program-launch-kit.html sec-8's mobile twin (sec-8-m), not a new sheet on this frame.
9eRecords sheet — nested over the Pulse tab, opens from the roster's “See all N ›” · 375, every state not built · 2026-09-02
Populated — bottom sheet, full height, rows stacked
detail sheet dims behind — nestedBackdrop · ✕ closes this sheet only
Attendees
24 seats · 19 booked · 5 left · synced 2 min ago
✕
Awaiting paymentWaiting list
Who's coming · 19
Sam Idrisawaiting payment
sam@idris.co · 1 spot · link sent Aug 30
Mark paid⋯
Lena Ortizpaid
lena@ortiz.studio · 2 spots · booked Aug 31
Priya N.paid
phone only · 1 spot · booked Aug 31
Waiting list · 3
Aisha Konewaiting
phone only · — spots · joined Sep 1
‹ PrevPage 1 of 2Next ›
Empty — activation day
detail sheet dims behind
Attendees
24 seats · 0 booked · 24 left
✕
◦
No one's booked yet

Your booking link is live. Share it and the first name lands here — usually within a day of posting.

Copy your booking link
no chips, no headers — absent, not disabled
Loading — the fetch in flight
detail sheet dims behind
Attendees
✕
skeleton rows at the real 56px height — never a centred spinner
Warm-stale — refetch failed over loaded rows
detail sheet dims behind
Attendees
24 seats · 19 booked · 5 left · last loaded 6 min ago
✕
Couldn't refresh — showing the list from 6 minutes agoRows below may be out of date. Try again
Who's coming · 19
Sam Idrisawaiting payment
sam@idris.co · 1 spot · link sent Aug 30
Lena Ortizpaid
lena@ortiz.studio · 2 spots · booked Aug 31
rows stay, dimmed, aged · verdict buttons REMOVED
Cold error — nothing ever loaded
detail sheet dims behind
Attendees
24 seats
✕
!
Couldn't load your attendees

Nothing's lost — this is a connection problem on our end. Your bookings are safe.

Try againClose

Or ping us if it keeps happening.

red is earned here — a fetch failure is a failure
Deep link, signed out
◍
Sign in to see your attendees

We'll bring you straight back to this list.

Sign in
/pulse?assistant=…&records=open while signed out → ProtectedRoute → sign-in. Return-to back to the sheet is a build gap (no platform-wide return-to exists — named, not invented). No row, count, or name renders before auth.
Deep link, signed in, NOT the owner
Pulse
Your active assistants
ActiveDetails →
Her own assistant ASST-1A1
On-Brand Support
Runs
12 · 100% healthy · 1d ago · $1.10
?assistant= resolves no assistant she owns (RLS returns nothing) → both params are dropped and Pulse renders her own wall. No sheet, no count, no "permission" wording — byte-identical to a deleted assistant. (Replaces the old in-surface "This list isn't here" state — there is no surface without the assistant. NEW (PRD debt) against AC-WSBK-31.)
Story · acceptance · design notes — shared with the desktop half: frame 9e ↑ (one note, both tiers). 375 adds: bottom sheet rises full height over the dimmed detail sheet; rows stack exactly as workshop-booking.html 13b; every control — verdicts, ⋯, ✕, chips, Prev/Next — is ≥44×44.
9fActivity sheet — NEW, nested over the Pulse tab · 375, three states not built · 2026-09-03
Populated — bottom sheet, full height, chips + pagination live HERE
detail sheet dims behind — nestedBackdrop · ✕ closes this sheet only
Activity
This assistant’s activity · 38 events in 7d
✕
24h7d30d
Booking confirmed — Priya M.$1.75 · paid6:14pm
Payment link relayed — Aisha Koneawaiting payment5:30pm
Class reminder queuedNeeds attentionView issue6:00pm
Booking confirmed — Daniel R.$1.75 · paid2:05pm
Answered a guest — “is parking included?”$0.08 · 0.9sJul 20
‹ NewerPage 1 of 4Older ›
Loading — the fetch in flight
detail sheet dims behind
Activity
✕
skeleton rows at the real row height, chips skeletoned too
Empty — nothing yet
detail sheet dims behind
Activity
Nothing yet
✕
◦
Nothing yet

Runs show up here as they happen.

no chips, no pagination bar — absent, not disabled
Story · acceptance · design notes — shared with the desktop half: frame 9f ↑ (one note, both tiers). 375 adds: bottom sheet rises full height over the dimmed detail sheet; every control — chips, ✕, Newer/Older — is ≥44×44.
10Post detail sheet — Overview tab R28 · R30
dimmed Pulse peeks — tap to return
Autumn retreat support✎
On-Brand Support Assistant · ASST-7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
What it does

It reads your Brain — prices, policies, hours, FAQs, and your brand voice — and answers guests in the voice you confirmed. Anything it can't ground in your knowledge gets handed to you.

How it works
01
Customer
“do you have space in September?”
02
Brain ✦
Grounds the answer in your facts ✦ AI
03
Assistant
Replies in your voice, in the same thread
tricky ones → routed to you
◎
Outcome
Guest helped, in your voiceYou never typed a word.
Key benefits
Answers while you sleep
Instant replies at the moment guests are deciding.
Sounds like you — because you confirmed it does
Your voice and policies, confirmed by you.
desktop 1180 crop — seated sheet, same anatomy as 9b
Autumn retreat support✎
On-Brand Support Assistant · ASST-7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect
What it does

It reads your Brain — prices, policies, hours, FAQs, and your brand voice — and answers guests in the voice you confirmed. Anything it can't ground in your knowledge gets handed to you.

How it works
01
Customer
“do you have space in September?”
02
Brain ✦
Grounds the answer in your facts ✦ AI
03
Assistant
Replies in your voice
◎
Outcome
Guest helped, in your voice
Key benefits
Answers while you sleep
Instant replies at the moment guests are deciding.
Sounds like you — because you confirmed it does
Your voice and policies, confirmed by you.
R28 — Pre/post Overview identical
  • Same `What it does` prose (one `long_description`), same chart, same benefits, both sides of activation — a second description would drift silently.
  • Post differs only in chrome (header identity, run controls, no stepper voice), never in copy.
R29 — Setup lives in Personalize
  • Read-back rows moved to post Personalize (frame 11) — one place to read setup, one place to change it.
R30 — Post tab set
  • Pulse · Overview · Personalize · Connect, Pulse first/default (first question is “is it working”, not “what is this”). Try removed post-activation (frame 12).
  • Pre-activation unchanged: Overview › Personalize › Connect › Try.
Build
  • Overview never renders a second `long_description` or post-only benefits list; Personalize (post) is the only tab with an Edit affordance for setup.

Both tiers drawn per R22. Archetype: assistant-detail-tabs.md (post-tab list + self-check #7).

11Post detail sheet — Personalize tab RETIRED · superseded by 9c / 13c · 2026-09-04

Editable “Edit” rows below are the pre-#4432 Personalize tab, kept here for history only. Peyton's 2026-09-04 lock (Option B) replaced this with the read-only locked mirror — nothing on any row is clickable, and setup changes happen only by starting a fresh assistant. Build from 9c / 13c ↓, never from this frame. The header below also predates the four-line hierarchy (9g) — left unfixed since the whole frame is historical.

dimmed Pulse peeks — tap to return
Autumn retreat support✎ASST-7Q1
On-Brand Support · active since Jul 21
$0.50 per session
⏸⏹✕
Pulse Overview Personalize Connect
Your setup
Greeting“Hey! You've reached Salt & Stone — how can we help?”Edit
Handling ruleshours · prices · availabilityEdit
Routed to yourefunds, anything it can't groundEdit

Changes take effect on the next run. Nothing already answered is rewritten. Brain readiness lives on Connect →.

desktop 1180 crop — seated sheet, same anatomy
Autumn retreat support✎ASST-7Q1
On-Brand Support · active since Jul 21
$0.50 per session
⏸⏹✕
Pulse Overview Personalize Connect
Your setup
Greeting“Hey! You've reached Salt & Stone…”Edit
Handling ruleshours · prices · availabilityEdit
Routed to yourefunds, anything it can't groundEdit

Changes take effect on the next run. Brain readiness lives on Connect →.

D-1 — Per-run knobs only
  • Brain Check module deleted here — Connect owns Brain readiness (T1155: apps · payment · Brain).
  • Tab shows exactly three rows — Greeting, Handling rules, Routed to you — each with Edit, opening the 60/40 split (frame 14) when the row lives in the Brain.
  • Quiet pointer only: “Brain readiness lives on Connect →”. Never a readiness count, category eyebrow, or Add/Review-in-Brain action here.
Build
  • Post-tab order (R30): Pulse · Overview · Personalize · Connect, no Try. “Changes take effect on the next run” — nothing already sent gets rewritten. Price uses the R27 treatment in the header.

Archetype: assistant-detail-tabs.md.

12“Waiting on you” — when the assistant hands a step back — mobile shipped · R31 · D-5
Surface 1 · the post card — a wave is ready to send
Active ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
214 signed up · page live · collecting
Runs
18 · 100% healthy · 6m ago · $4.50
Waiting on youSend the launch · wave 2 Review
Same card, wave 2 sent — the row goes, collecting continues
Active ▶⏸⏹ Details →
October cohort waitlist ASST-4B8
Waitlist + Launch
228 signed up · wave 2 sent Jul 22 · still collecting
Runs
19 · 100% healthy · 2m ago · $5.00
For contrast · an assistant with no staged step, ever
Active ▶⏸⏹ Details →
Autumn retreat support ASST-7Q1
On-Brand Support
5 connected
Runs
142 · 96% healthy · 2h ago · $18.40
Surface 2 · 375 — the action sheet, ONE screen
dimmed Pulse peeks — tap to return
Send the launch
October cohort waitlist · Waitlist + Launch
✕
Which waves
○Wave 1 — early list
96 people · sent Jun 30
sent
✓Wave 2 — October open
118 new · 4 from sold-out
214 selected

Nobody gets the same wave twice.

Before it goes
✓Your message is written
✓WhatsApp is connected
✓Wallet has enough for this send
What they'll get
As it arrives in WhatsApp
Hi Ana — October dates are open. You're on the early list, so you've got first pick until Friday. Here's the link to hold your place: …

Wrong words? Edit in Personalize →

Try it on yourself first shipped
Send a test to my own numberDrawn as the intended affordance — the number it needs has no input anywhere today (see note) Send test
Send to 214 people · $0.50

101–500 people is the $0.50 band. This one can't be unsent, and there's no retry — nothing goes out until you tap it.

Surface 2 · 375 — template still with WhatsApp (Pending)
dimmed Pulse peeks — tap to return
Send the launch
October cohort waitlist · Waitlist + Launch
✕
Pending · WhatsApp is reviewing this message Meta checks every launch message before it can go out. Yours went in 6 hours ago; most come back within a day or two. Nothing is wrong, and nothing is lost.
While you wait
Read it overChange the words now and the new version goes for reviewEdit in Personalize →
See who's on the list214 people, still growingSee the list →
Send to 214 people · $0.50

We'll tell you the moment it's approved — you don't have to check back.

Surface 2 · 375 — nobody to send to yet
Send the launch
October cohort waitlist · Waitlist + Launch
✕
Which waves
○Wave 2 — October open
Nobody has joined this wave yet
0

Your signup page is live and collecting. We'll put this back on your Pulse card the moment there's someone to send to.

Send the launch

No recipients, no charge.

Story · acceptance · design notes — shared with the desktop half: frame 12 ↑ (one note, both tiers).
§5 · Change
13Reactivation — the chooser, in current chrome R18 · R19 · CPO copy verbatim
375 · chooser dialog over the dimmed Past tab
Past tab dims behind — tap outside to cancel
Turn “Summer retreat support” back on
Two ways to do it. Neither one loses anything.
Reactivate
Same setup, same list — new signups join as the next wave.
What comes back
Greeting“Hey! You've reached Salt & Stone…”
AppsWhatsApp Business · MystFlo AI
Brain7 of 7 ready
Reactivate

Rename it first? Autumn retreat support ✎

Start fresh
A new, separate instance — your old one stays in Past, nothing's overwritten.
Start fresh
Desktop 1180 · same dialog, centered over the dimmed page
Pulse · Past dims behind — Escape or click outside to cancel
Turn “Summer retreat support” back on
Two ways to do it. Neither one loses anything.
Reactivate
Same setup, same list — new signups join as the next wave.
What comes back
Greeting“Hey! You've reached Salt & Stone…”
Handling ruleshours · prices · availability
AppsWhatsApp Business · MystFlo AI
Brain7 of 7 ready
Reactivate Rename ✎
Start fresh
A new, separate instance — your old one stays in Past, nothing's overwritten.
Start fresh
R18 — Dialog, not a sheet
  • `ModalWrapper presentation="dialog" size="sm"` per `reactivation-flow.md` — a small two-card decision, not onboarding. Visual language updated only; reclassifying to a bottom sheet violates the archetype's FORBIDDEN list.
R18 · R19 — Copy, BINDING
  • Reactivate → “Same setup, same list — new signups join as the next wave.” Start fresh → “A new, separate instance — your old one stays in Past, nothing's overwritten.” Never “delete”/“replace”.
  • Two cards only (`quick_resume`, `start_fresh`); `review_config` stays invisible plumbing, never a card. No config editing at reactivate time.
  • Stopped/Completed cards (frame 8) carry one footer CTA, Reactivate →; “Start fresh” lives inside the chooser only.
“Don't ask me next time” — shipped
  • Control: `ReactivationConfigReview.tsx:341`; read by the auto-resume branch at `:134` — when checked, the chooser is skipped entirely, card's Reactivate → goes straight live.
  • Persistence: per-assistant `localStorage mystflo_skip_reactivation_review_{id}`.
Build
  • Checkbox ships — omitting it deletes the bypass path. Copy fix: shipped string still reads “always Quick Resume” — `quick_resume` is internal, must read “always Reactivate” founder-facing (archetype wireframe needs the same fix).
13bThe two flows, end to end R19
Full activation — first time
01Explore cardtap for details
02Overviewwhat it does, how it works
03PersonalizeBrain Check + your fields
04Connectapps · wallet · same Brain Check
05Tryread-back · test if the type has one · name it
06Activating5 steps · can fail & roll back
07Live in Pulseor live-for-replies, launch pending

375 — the same seven steps stack vertically, one box per row, the thread running down the left.

Start fresh — from a Past assistant
01Past cardStopped or Completed
02Reactivate →one CTA, both states
03Choosertwo cards
04Start freshwizard opens PREFILLED from the old setup
05Personalize → Connect → Trychange anything; name the new one
06New instance livenew ASST-id · old one still in Past
03aReactivatethe other branch
04aPreflightexpired token? wallet empty? → Fix modal
05aSame instance live againsame ASST-id · “Reactivated” lands in the Pulse tab
02bReactivate →she checked “Don't ask me next time”
03bChooser SKIPPEDnever drawn — the saved preference auto-runs Reactivate
04bSame instance live againone tap from Past card to running

The 02b row is the bypass the “Don't ask me next time” checkbox buys — shipped today (`ReactivationConfigReview.tsx:134`). Preflight still runs; only the chooser disappears.

R19 — Two sequences
  • Start-fresh: new instance, new ASST-id, old one stays in Past. Reactivate: same instance, same id, “Reactivated” line in its Pulse tab. Start-fresh opens the same wizard prefilled.
  • Reactivate branch runs a real preflight (expired tokens, empty wallet, changed sheet → Fix modal) before anything activates — never a mid-reactivation failure.
Build
  • Preflight gate runs before activation on the reactivate branch, never after; start-fresh always issues a new ASST-id, never mutates the Past record.
13cPersonalize tab — the locked mirror — mobile A6 presentation · REDRAWN 2026-09-04, supersedes the ledger
375 · ACTIVE — at rest
dimmed Pulse peeks — tap to return
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Pulse Overview Personalize Connect

This is what's set for this round — nothing edits in place. Start fresh with a new assistant → (⋯, top right). Brain readiness lives on Connect →

01 · Your workshop
Workshop name
Saturday Sound Bath Workshop
Date
Sat Feb 9 · 11:00
Price
USD45
Seats
12
03b · Where guests book
In this chat
WhatsApp's own tap-through form.
Your own booking form
Bookings land in your sheet.
04a · Booking messages
Payment ask
Your seat is held — it's confirmed the moment your payment lands.
Booking confirmation locked
Meta-approved
You're booked, Maya — see you Feb 9 at 11:00.
03a · Where guests reach you
Booking link
wa.me/1555…?text=book
·· preview — “In this chat” · once your Flow is live ··
hi! any spots left for tuesday's class?
Wheel Throwing Class — Jul 28, 2026. Tap below to grab your spot:
Wheel Throwing Class
Tue 28 Jul · $42 per seat · 3 seats left
Name
Email
Party size
2026-07-28
Confirm booking
Real form fields after activation — never faked here
Your details are in, Maya. Your seat for Wheel Throwing Class is held — it's confirmed the moment your payment lands.

Here's how to pay for your spot — reply once you've sent it and I'll confirm.
↗ Pay now
When “QR code” is picked (04b), this bubble sends instead:
your QR as an image — the same payment-ask words as its caption
done — just sent it!
you tap Mark paid — or your roster shows it
You're booked — Wheel Throwing Class
Hi Maya, it's Priya — your seat for the Wheel Throwing class is confirmed. We'll send a reminder before class. Reply here with any questions.
Then: the Class reminder (04a) — same thread, 1 day + 1 hour before class

Works the same whether they tapped your wa.me link or typed this directly — the AI reads intent, not just the word.

·· preview — “Your own booking form” (03b) ··
hi! any spots left for tuesday's class?
Yes! Here's where to book: forms.emberclay.com/wheel — you'll pick your spot and pay there. Shout if anything's unclear.
That relay is the whole guest experience — no capture, no payment ask (AC-WSBK-14). Confirmation + reminders fire from your roster tick.
375 · a field left blank at signup
dimmed Pulse peeks — tap to return
Total seats
Not set yet

Same string ConfigFieldRenderer.tsx's formatLockedFieldValue() already returns for an empty value — never a silent schema default standing in as if the founder chose it.

Story · acceptance · design notes — shared with the desktop half: frame 9c ↑ (one note, both tiers). 375 specifics: .field/.opt-radio reflow full-width, same as the pre-activation Configure step at this width — no bespoke mobile row grammar. Paused renders the identical .m-body, header only differs (see 13g). Preview, corrected 2026-09-04: renders exactly what this instance's OWN pre-activation mobile Personalize frame draws — workshop-booking.html sec-3's full-inline preview (both variants, stacked below the form, no dock), copied verbatim, un-dimmed, outside the .m-body.pz-locked wrapper. NOT this file's own D2-locked slide-up-dock pattern (sec-4e's .pvpill/bottom-sheet) — an earlier pass here used that dock instead, on the theory that it's the current canonical mobile-preview mechanism; Peyton's "carry over whatever pre-activation actually draws, unchanged" ruling reversed that in favor of matching this specific instance's actual source frame byte-for-byte. Flag for whoever owns D2/workshop-booking.html next: that source frame (sec-3) itself doesn't use the dock either — it predates the D2 lock (`design-decisions.md` "D2 — mobile Personalize preview is Variant A: slide-up on demand") and is stale relative to it. Copying it verbatim here means 13c-m inherits that same drift rather than fixing it; the fix, if wanted, belongs at the source (bring workshop-booking.html sec-3 up to D2 first), not invented independently in the post-activation mirror.
13gPost detail header — four lines at 375 amends D-4 · 2026-09-04

Mobile tier of 9g ↑. Same four lines, same order; L1 wraps to two lines at most (line-clamp-2, the existing title rule), L2–L4 are single-line and truncate from the right. The control cluster keeps its 44px hit areas and never wraps under the title.

375 · booking type, named by its subject
dimmed Pulse peeks — tap to return
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Pulse Overview Personalize Connect

Below: the Pulse tab body, unchanged (frame 9). The header is the only thing this frame draws.

375 · no subject yet — L1 falls back to the type, L2 is the id
dimmed Pulse peeks — tap to return
On-Brand Support Assistant✎
#7Q1
Active · $0.50 per session · live since Jul 21
Last run 2h ago
▶⏸⏹⋯✕
Pulse Overview Personalize Connect

The type is never printed twice. Naming it (✎) promotes the founder's word to L1 and drops the type to L2 — the booking crop's shape.

375 · ⋯ menu open — Rename · Start fresh
dimmed Pulse peeks — tap to return
Saturday Sound Bath Workshop✎
Workshop Booking Assistant · #SPQ
Active · $1.75 per run · live since Sep 2
Chatting now
▶⏸⏹⋯✕
Rename
Start fresh with a new assistant →
A new instance, new id, prefilled from this one. This one keeps running until you stop it.

Same two items as desktop. Pause / Stop stay ⏸ ⏹. “Switch account…” stays in Connect's status menu (13d).

Story · acceptance · design notes — shared with the desktop half: frame 9g ↑ (one note, both tiers).
13dConnect tab — Switch account in the status menu, mobile shipped · A6 mute · 2026-08-17

Mobile tier of 9d ↑. Both rows keep their status chevron even where the badge carries none — the two arrows answer different questions (5b). The muted Switch account… is the .dim flavour: tappable, and what it opens is a decision with two live paths, so it earns the notice panel rather than 5b's inline .off reason line.

375 · ACTIVE — "Switch account…" muted in the menu
dimmed Pulse peeks — tap to return
October cohort waitlistASST-4B8
Connect · active since Jul 21
✕
Pulse Overview Personalize Connect
Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌄
Payment Stripe
Takes the deposit for this booking
Connected ⌃
Disconnect
Switch account…
Pause to switch this connection Switching mid-run risks a deposit landing on the wrong Stripe account. Pause this assistant to connect a different one — or start a new instance instead.
Pause to switch Start a new instance →

No badge caret (one app per role) and no standalone button — Switch account lives in the status menu, visible but MUTED while Active; tapping it opens this notice, never acts. Reconnect still appears if a connection breaks. Cropped to the apps section under demonstration; AI Model / Storage (B3) are omitted from the crop, not the tab.

375 · PAUSED — "Switch account…" live
dimmed Pulse peeks — tap to return
October cohort waitlistASST-4B8
Connect · paused by you · Jul 29
✕
Pulse Overview Personalize Connect
Connect apps
Communication WhatsApp Business
Where your guests already message you
Connected ⌃
Disconnect
Switch account…
WhatsApp Business
○Use a different number
Opens Connects to link a different WhatsApp number
Payment Stripe
Takes the deposit for this booking
Connected ⌄

Paused lifts the mute — same item, same place, now live; it opens the switch on the app it targets, then Resume. The menu's SHAPE never changes between Active and Paused, so she learns one menu and only a line's muting moves. On a multi-app row this item instead greys out with its reason and points at the badge, exactly like Disconnect (frame 5b).

Story · acceptance · design notes — shared with the desktop half: frame 9d ↑ (one note, both tiers).

The host split is already signed at 14. This frame is the next beat: Share anything, from inside that Brain pane. Two panels stay two panels. The sheet never unfolds a second 40/60 inside the 40%.

WALKTHROUGH — one job, two panels · keep this chrome for now

 1  Assistant rises          do something · bottom sheet
 2  Brain slides from left   go somewhere · 40% page pane · frame 14 at rest
 3  Share anything rises     SAME sheet as /brain, contained in the pane
                             not a centered dialog · ModalWrapper presentation="sheet"
 4  Empty → proposal → honest-empty   still two panels · frames (1)(2)(3)
 5  Close                    section editor returns · assistant never left

 Why it can look like a card: the sheet chrome (reveal gap, 18px radius, pane dim)
 is one size down. The page peeks above a viewport sheet; Brain peeks above this
 one. Accepted for now — do not invent a second Share mechanic or fill-the-pane swap.

 Broken (never drawn)     [ digest 16% | share 24% | assistant ]
 Target                   [ opaque stacked Share | assistant 60% ]
(0) AT REST — Brain already open on the left. Same split as 14. Share has not risen yet. Brain is the destination. Share is the next rise, inside this pane.
‹ Brain · Business basics
What you run

The one line guests hear first. Your assistants quote this back.

Retreats and workshops…
Share anything Save to Brain
On-Brand Support
Connect · 03 Brain Check
From your Brain — nothing to re-type
Business basics 1 of 2
○What you run
Add what you run
Adding…
✓Business name
Confirmed
Try reads this same check back as one line — it never re-asks.
(1) EMPTY composer — the same sheet rises inside the 40%. Peek + radius are the sheet, one size down — not a dialog. Two panels. The assistant stays the job.
‹ Brain · Business basics
What you run
Retreats and workshops…
Share anything
✕
What this fills · 50% of required
what you runMissing
your business nameConfirmed
one offeringMissing
Add to your Brain

Read your site, paste anything, drop a file, or link a doc — we’ll read it and sort it into your playbook.

Paste anything — about page, FAQ, policy — or drop a file.
Save to my Brain
On-Brand Support
Connect · 03 Brain Check
From your Brain — nothing to re-type
Business basics 1 of 2
○What you run
Add what you run
Adding…
✓Business name
Confirmed
Try reads this same check back as one line — it never re-asks.
(2) PROPOSAL riding — same stacked sheet, composer stays mounted, assistant still live
‹ Brain · Business basics
Share anything
✕
What this fills · 63% of required
what you runDrafted
your business nameConfirmed
Saved firstwe only take bank transfer in Bali — no card on arrival
What you run
All-inclusive surf & yoga retreats in Canggu.
✓ UseDiscard
On-Brand Support
Connect · 03 Brain Check
From your Brain — nothing to re-type
⚠What you run
Draft waiting
Review
(3) HONEST-EMPTY — 15j twin. Composer hidden behind named exits; still two panels. Closing Share anything returns the section editor. The assistant never left.
‹ Brain · Business basics
Share anything
✕
What this fills · 50% of required

Read it — nothing to confirm

We read it — nothing here fits a field yet. Add it directly and we’ll keep it.

Add or edit directly Try again
On-Brand Support
Connect · 03 Brain Check
From your Brain — nothing to re-type
Business basics 1 of 2
○What you run
Add what you run
Adding…
✓Business name
Confirmed
Try reads this same check back as one line — it never re-asks.
Story
  • She is finishing On-Brand Support. Brain is already open on the left. She taps Share anything — the same sheet rises inside that pane; the assistant stays the job.
Acceptance AC-BRAIN-100 · 101 · 102 · AC-BRAINGATE-12
  • AC-BRAIN-100 / AC-BRAINGATE-12 · hosted share stays two panels — Given the assistant split is open and Share anything is tapped from the Brain pane, when the sheet opens, then the host 40/60 remains the only split: Share renders as an opaque stacked sheet inside the 40% pane, the assistant 60% stays live, and no playbook digest column is minted beside the composer.
  • AC-BRAIN-102 · no bleed-through — Given Share anything is open inside the Brain pane, when the section editor is still mounted underneath, then the sheet chrome is opaque (not flushSplit) so the editor does not paint through the composer.
  • AC-BRAIN-100 · it is the sheet, not a dialog — Given Share opens from the Brain pane, when it mounts, then it is ModalWrapper presentation="sheet" (rise, reveal gap, radius) contained in the pane — never a centered confirm.
  • AC-BRAIN-101 — Standalone /brain at ≥1024 keeps f15’s internal 40/60 — that sheet owns the full stage. brain.html f15 ↗
  • Close returns the section editor. The assistant never left.
Design notes
  • Motion is unchanged: do something rises, go somewhere slides from the left, nothing enters from the right. Share is a task, not a destination.
  • ModalWrapper is the sheet host. presentation="sheet" is the locked rise. The card-on-Brain look is that chrome one size down (pane peek, 18px radius, pane dim). Accepted for now — do not swap the left pane or invent a second Share surface.
  • Stacked digest = f15a / BrainStackedFillsDigest. The co-pane column is only when this sheet owns the viewport. Rejected: B (swap the pane) · C (park the assistant for full-stage f15).
  • 375 / 768 already match the stacked sheet. Do not invent a split below 1024.

Components: BrainShareSheet.tsx · BrainSplitHost.tsx · ModalWrapper.tsx presentation="sheet" · useSplitLayout. Spec: modal-slide-choreography-architecture.md §1. Sibling frame: brain.html f15.

14One mechanic, three destinations (apps · funds · Brain) — mobile R20 · R35 · D-1 Brain pane redrawn 2026-09-12 (Peyton): the Book, and a takeover
375 · no split at this width anyway — the destination is the full page (drawn once, generalizes to all three). For Brain this is the same full-cover takeover as desktop, not a tier collapse: it covers the screen at every width, so there is no peek edge — Close is the way back.
Close·Your playbookv3
05Assistant reads
How you run

Refunds, deposits, and changes — in your words.

Your policies — what it covers · the rule you actually apply
01a policythe rule
02a policythe rule
03a policythe rule

Nothing here yet — this is the shape it takes. Teach your Brain ›

You'll land back on Connect with this row ticked.

Teach your Brainadd · change · remove

Same push, same peek-edge/Esc return, on every destination — this Brain example is drawn once and stands for Connects and Top-up too. Change card is the next frame.

Story · acceptance · design notes — shared with the desktop half: frame 14 ↑ (one note, both tiers).
14cChange card — Billing only from the Top-up chip — mobile funds-first · 2026-08-18
375 · Top up first (tap funds on Connect)
◄ peek edge · tap to return to Connect
Wallet · Top up
Top up

Runs draw from this. Nothing else is charged.

Amount
●$25
○$50
○$100
Visa ···4242Tap to change Change →
Add $25.00
375 · Change card (tapped the chip — only Billing entry from setup)
◄ peek edge · tap to return to Top up
Billing · Card
Payment method

The card Top up will charge.

Visa ···4242Default · expires 08/28 Default
Replace this card
Card number
Save card

Connect never opened Billing.

Story · acceptance · design notes — shared with the desktop half: frame 14c ↑ (one note, both tiers).
14bThe co-edit pane's missing states — mobile shipped · R35 states

There is no split below 1024, so every state below is the same full-screen push — the 768 tablet tier is this same frame, wider (drawn in the desktop half). The peek edge is the only way back, on every state.

375 · LOADING — identity instant, form waits
◄ peek edge · tap to return to Connect
Connects · Email
Resend
 
 

The wizard already told us which app — only Resend's own form is loading.

375 · ERROR — the failure sits under the field she typed in
◄ peek edge · tap to return to Connect
Connects · Email
Resend

Sends your launch emails from your own address.

API key * required
re_••••••••••••3f2a

Resend didn't accept that key. Copy it again from Resend — it starts with re_ and has no spaces.

Try again

Going back now leaves the row exactly as it was — nothing half-saved.

375 · SETTLE — the tick holds a beat, then the push slides away on its own
◄ peek edge · tap to return to Connect
Connects · Email
✓Resend connected

Launch emails will send from your own address.

◄ taking you back to Connect…

375 · ABANDON, after submit — she's back on Connect, the row finishes without her
01 · Connect apps
Communication WhatsApp + Resend ▾
The launch goes out on WhatsApp and email
Resend is still connecting — this row updates on its own
Connecting…
Storage Google Sheets ▾
Where your signups land
Connected ⌄

Leaving the push is navigation, not cancelling. Nothing submitted → nothing saved and no confirm dialog; already submitted → it lands on its own and this row flips itself.

375 · OAUTH RETURN — fresh tab, and she lands back inside the wizard
Waitlist + Launch
Connect · 01 Connect apps
Resuming where you left offYour answers from Personalize are exactly as you left them.
Communication WhatsApp Business
Where your guests already message you
Connected while you were away
Connected ⌄
Storage Google Sheets ▾
Where your signups land
Connected ⌄

No push reopens — the job it was opened for is done. She never presses a “continue” to get her own work back.

Story · acceptance · design notes · the two rulings (geometry, and form-as-pane) — shared with the desktop half: frame 14b ↑ (one note, both tiers).
14dShare anything from the Brain pane — stacked sheet, no third column NEW · stage-ownership view at desktop ↑↓
375 · Share anything is the full-screen sheet over the Brain push — already shipped
◄ peek edge · tap to return to Connect
Share anything
✕
What this fills · 50% of required
what you runMissing
your business nameConfirmed

Read your site, paste anything, drop a file, or link a doc.

Paste anything — or drop a file.
Save to my Brain
768 · same stacked sheet, wider — still no split (below 1024)
◄ Brain · tap to return to Connect
Share anything
✕
What this fills · 50% of required
what you runMissing
your business nameConfirmed
Paste anything — or drop a file.
Save to my Brain
Story · acceptance · design notes — shared with the desktop half: frame 14d ↑ (one note, both tiers). Same presentation="sheet" rise as desktop, full-width because there is no split below 1024. Not a dialog. Do not invent a third column here.
§6 · Money
15Billing — usage by assistant, wallet language D4 identity
Billing
What each assistant cost you this month.
Wallet
BalanceRuns draw from this — nothing else is charged $41.20
Top up
This month by assistant
Autumn retreat support ASST-7Q1$18.40
On-Brand Support · 142 runs
Deposit chaser ASST-5T3$30.80
Deposit Chaser · 88 runs
October cohort waitlist ASST-4B8$4.50
Waitlist + Launch · 18 runs
Also this month
Brain & AI operationsread-my-site, drafts, refinements$6.10
App costsWhatsApp and Stripe bill your own accounts directlynot ours
Billing — desktop 1180 crop
Same rows, wider bars, wallet pinned right.
This month by assistant
Autumn retreat support ASST-7Q1$18.40
On-Brand Support · 142 runs · $0.50 per session
Deposit chaser ASST-5T3$30.80
Deposit Chaser · 88 runs · $0.35 per run
October cohort waitlist ASST-4B8$4.50
Waitlist + Launch · 18 runs · $0.25 per run
Wallet
$41.20

Runs draw from this. Nothing else is charged.

Top up

App costs (WhatsApp, Stripe) go to your connected accounts.

D4 · D3 — Identity + wallet language
  • Every usage row leads with instance name + ASST-id, template name on the sub-line — same order as Pulse.
  • Wallet language only: balance, draw, top up — “payment” never appears.
  • App costs named as BYOK, excluded explicitly — never read as “MystFlo charges for WhatsApp”.
  • Billing is the ONE home for account-level money; Pulse tab links here, never duplicates totals.

Both tiers drawn per R22.

Copy on these frames is provisional — Chief Product draft 2026-09-25, pending Peyton’s approval (#5311). Placement and structure are the contract; strings may still change.

Pulse Overview · Support stopped on its own (wallet empty) → View issue → sheet
Pulse
OverviewActivePastRuns
Needs your attention 1
Ember Clay support
Not running — wallet empty · 1 booking assistant waiting
View issue →
Breakdown
Ember Clay supportOn-Brand Support · ASST-2K8Paused — needs you
Weekly wheel-throwing classWorkshop Booking · ASST-4L9Active · waiting on Support
Issue✕
PausedEmber Clay support ASST-2K8
Paused — wallet empty
Weekly wheel-throwing class is still live: a booking link or QR tap still gets the form. But guests who ask a question get no answer until Support runs again.
Top up and Support picks up from the next message.
Paused Sep 24
Add funds
Pulse wall · Active tab — booking card keeps Active; Support’s ⏸ ⏹ are dimmed
Workshop Booking — still Active, waiting on Support
Active ▶⏸⏹ Details →
Weekly wheel-throwing class ASST-4L9
Workshop Booking
Waiting on Support — questions go unansweredⓘ
Bookings
9 confirmed · 2 awaiting payment · last 1d ago
Link and QR taps still bookView Support →
On-Brand Support — paused by the system (8e grammar)
Paused ▶⏸⏹ Details →
Ember Clay support ASST-2K8
On-Brand Support
Wallet empty — top up to keep runningⓘ
Sessions
41 · 96% healthy · 1d ago · $20.50
1 booking assistant waiting on thisTop up →
Blocked — tapping ⏸ or ⏹ on Support while a booking assistant is live
Pulse · Active dims behind — Escape or click outside to close
Pause your booking assistants first
On-Brand Support answers guests for the booking assistants below. While any of them is live, Support stays on.
Weekly wheel-throwing classWorkshop Booking · Active
Sunset SessionEvent Booking · Active
Open booking assistants
8f — Support can’t be paused under a live booking assistant; when it stops on its own, one fix Peyton 2026-09-25 · #5311 · NOT built
  • User story. As a founder with a booking assistant live, I can’t switch Support off by accident. If Support stops on its own, Pulse tells me what my guests are missing and gives me the one action that gets it running again.
  • Acceptance. Same Band A row + issue-sheet door as AC-PULSE-19 ↗ · NEW (PRD debt): ⏸ / ⏹ on Support while any booking assistant is live opens the blocked dialog — no confirm, no override; its one action opens the live booking assistants · NEW (PRD debt): the attention row appears only for involuntary causes — error auto-pause (Resume Support), wallet empty (Add funds, = 8e), Brain too thin (Finish in Brain) · NEW (PRD debt): the booking card stays Active, with “waiting on Support” on its meta line; link and QR taps still send the form.
  • One row, on the thing to fix. The attention row is Support’s, and it names how many booking assistants are waiting. There’s no second row per booking card, so the wallet case is 8e’s row with that clause added. The booking card carries the signal on the wall. Lantern is the one “needs you” moment in each view. D-3 holds: Support’s system pause is amber (the 8e verbatim status line), and the booking badge stays emerald.
  • Blocked, not confirmed. Uses the existing centered dialog (a sheet at 375) with a read-only list and a single primary action. Support’s ⏸ and ⏹ render dimmed on its card for as long as a booking assistant is live. Both assistants are charged only when used, so a waiting booking card costs nothing.
  • Not claimed here. Any holding line a guest sees while Support is down belongs to the CTO routing spec for #5311. These frames promise only what the ruling states: link and QR taps still book.
8f — 768Support stopped on its own under a live booking assistant — issue sheet at tablet #5311 · not built desktop ↑↓

Copy on these frames is provisional — Chief Product draft 2026-09-25, pending Peyton’s approval (#5311). Placement and structure are the contract; strings may still change.

768 · full-width band, prose column capped at 720
tablet 768 — Pulse Overview under a soft dim, sheet rises to content height
Pulse
OverviewActivePastRuns
Needs your attention 1
Ember Clay support
Not running — wallet empty · 1 booking assistant waiting
View issue →
Breakdown
Ember Clay supportOn-Brand Support · ASST-2K8Paused — needs you
Weekly wheel-throwing classWorkshop Booking · ASST-4L9Active · waiting on Support
Issue✕
PausedEmber Clay support ASST-2K8
Paused — wallet empty
Weekly wheel-throwing class is still live: a booking link or QR tap still gets the form. But guests who ask a question get no answer until Support runs again.
Top up and Support picks up from the next message.
Paused Sep 24
Add funds

768 samples the U8 continuum; it isn’t a third layout. Same rule as 8e: the Overview reflows and the sheet is one column capped at 720. Wall cards follow the Pulse wall’s own two-up step, and the blocked dialog is the centered dialog.

8fSupport under a live booking assistant — three involuntary causes + blocked pause · 375 Peyton 2026-09-25 · #5311 · not built desktop ↑↓

Copy on these frames is provisional — Chief Product draft 2026-09-25, pending Peyton’s approval (#5311). Placement and structure are the contract; strings may still change.

Wallet empty — Add funds (8e sheet, plus the booking clause)
OverviewActivePastRuns
Needs your attention 1
Ember Clay support
Not running — wallet empty · 1 booking assistant waiting
View issue
Issue✕
PausedEmber Clay support ASST-2K8
Paused — wallet empty
Weekly wheel-throwing class is still live: a booking link or QR tap still gets the form. But guests who ask a question get no answer until Support runs again.
Top up and Support picks up from the next message.
Paused Sep 24
Add funds
Error auto-pause — Resume Support
OverviewActivePastRuns
Needs your attention 1
Ember Clay support
Not running — stopped after repeated errors · 1 booking assistant waiting
View issue
Issue✕
PausedEmber Clay support ASST-2K8
Paused — it hit repeated errors
Weekly wheel-throwing class is still live: a booking link or QR tap still gets the form. But guests who ask a question get no answer until Support runs again.
What happened · 3 replies in a row failed to send — WhatsApp rejected the message.
Try it again — if it fails again, we’ll show you what to fix.
Paused automatically · Sep 24
Resume Support
Brain too thin — Finish in Brain
OverviewActivePastRuns
Needs your attention 1
Ember Clay support
Not running — the Brain is too thin to answer from · 1 booking assistant waiting
View issue
Issue✕
PausedEmber Clay support ASST-2K8
Paused — not enough in your Brain to answer from
Weekly wheel-throwing class is still live: a booking link or QR tap still gets the form. But guests who ask a question get no answer until Support runs again.
Missing · prices · cancellation policy
Fill those in and Support resumes on its own.
Paused automatically · Sep 24
Finish in Brain
Blocked — pause booking first
Active tab dims behind — tap outside to close
Pause your booking assistants first
On-Brand Support answers guests for the booking assistants below. While any of them is live, Support stays on.
Weekly wheel-throwing classWorkshop Booking · Active
Sunset SessionEvent Booking · Active
Open booking assistants
Story, acceptance, and design notes are shared with the desktop half (one note for every tier). “Open booking assistants” lands on Pulse → Active, filtered to the live booking cards.
Guest
This step is 375. No 1180 drawing — use the Mobile size.
768 not yet drawn for this flow. Desktop and 375 are the contract.
This step is 1180. No 375 drawing — use the Desktop size.
7 · Components the reusable parts library — reference only; every part is proven in a full screen in sections 5/6, or in its owning surface file
Cards + sheets (names from code)
  • AssistantSummaryCardPre — R34 fixed-slot anatomy, three CTA contexts, one shell. In context: frames 1, 2. Full-page seating: explore.html, team.html.
  • AssistantSummaryCardPost — R13/A4 geometry, A5 control row (▶ ⏸ ⏹, inapplicable = .off, never removed). In context: frames 8, 8b. Full-page seating: pulse.html.
  • AssistantDetailModalPre / Post on ModalWrapper presentation="sheet" — 375 bottom sheet + desktop seated sheet, full-width band chrome. In context: frames 3, 9b, 10. Pass-bar: archetypes/assistant-detail-tabs.md, sheet-slide-panel.md.
Flow mechanics
  • ShareSheetModal — R25 sheet presentation, R33 four destinations. In context: frames 1b (desktop + mobile).
  • Wizard tab bodies (Personalize · Connect · Try) — R32 preview media, B2/B3 role-row grammar, R11 honest test. In context: frames 4a–6.
  • DestinationPicker role-row expansion — B9 label = role, badge = current selection. In context: frame 5b (Future states: F3).
  • PageSlideOver / BrainSlideOver — R35 one split mechanic, three destinations (apps · funds · Brain); Billing only from the Top-up card chip. In context: frames 14 · 14c.
  • Pending-action row (“Waiting on you”) — R31 flag-on-card, max one, not a status colour. In context: frame 12.
  • Status vocabulary parts — ladder legend (D-3), app chips (R24/R15/B1), read-back block, notices. In context: frames 8b, 5, 6, 7.
Pulse-tab template + typed slots R37, 2026-09-03 — Peyton: "right column as principle"
  • PulseTabTemplate — the L/R/B rule for every assistant type: exception row (if any) → metrics(L) + slot(R) as a pair → activity(B). In context: frames 9b, 9b-x, 9b-r, 9b-k.
  • PulseSlot.records — booking · waitlist · checkout; noun is a prop (Attendees / Signups / Orders); roster is the FIRST item in the slot, booking link/share/flyer under it. In context: frame 9b-r.
  • PulseSlot.chat — direct wa.me/{phone} share row, no booking prefill. In context: frame 9b.
  • PulseSlot.generation — piece-readiness preview + Open kit › into the existing LaunchKitReviewSheetBody; amends the 2026-08-22 "kit body replaces the whole tab" exception. In context: frame 9b-k.
  • ActivitySheet — nested full-width slide-up carrying the range chips + ‹ Newer · Page N of M · Older › pagination the tab's 5-row preview doesn't. In context: frame 9f.
  • RecordsSheet — nested full-width slide-up, every state, FilterChipGroup + PaginationBar. In context: frame 9e.
  • Assistant files never redraw this tab — they carry a revisit card to the matching 9b-* frame and refine slot copy only (see each file's own Pulse-tab section).
Core rule — full screen first, part second
  • No part above is introduced here first — section 7 indexes what sections 5/6 already prove in context (canon: an add-on or state change is never only a component snippet).
  • Known below-bar frame: 9d is cropped to the apps section only (self-flagged in its Build note) — the full post-activation Connect tab is not yet drawn as its own frame.
8 · Future design Part II — post-launch or not-yet-built, build-later contracts · never a build target
Overview› Personalize› Connect › Try
Your listing
Product name * required
Handwoven alpaca throw — moss
Where it sells
Etsy ✕Shopify ✕+ add platform
One thing buyers should know
e.g. hand-dyed in small batches — sample until you type
Listing draft · Etsy
Handwoven alpaca throw — moss
Generated description appears in Try → — written from your Brain's voice and this listing's facts, never faked here
Materials, care, and shipping lines — generated in Try →
·· preview ··
P2 build contract plan-assistant-preview-universal-2026-07
  • Behaves like browser medium: form fixed 440px, preview flex-1, row cap 1440px token.
  • Minimal hairline “page” shell, no fake OS chrome, watermarked.
  • Founder facts go live per-field; every AI-generated region is a static labeled placeholder.
  • R32: shell stretches to the full column height, top-aligned; long drafts scroll inside.
Build
  • AI-generated regions render as labeled placeholders pre-run, never a faked draft; founder-entered fields go live immediately.
Overview› Personalize› Connect › Try
Your roster columns
What each row is
A booking
Columns it fills
Guest ✕Dates ✕Deposit ✕Status ✕+ add column
Guest
Dates
Deposit
Status
Ana M.sample
Sep 2–8
$540 paid
Confirmed
Jonas K.sample
Sep 2–8
awaiting
Held
Priya S.sample
Oct 6–12
$540 paid
Confirmed
·· preview ··
P2 build contract — WIDE medium
  • Preview flex-1 beside the fixed 440px form, row capped at 1440px token.
  • Column headers are the founder's own (live, white); rows are labeled sample data.
  • Hairline table shell, header row + 3–4 rows, no OS chrome.
  • R32: table shell fills the column height, top-aligned; rows extend down the column.
Build
  • Column headers always reflect the founder's own field names; sample rows never render un-labeled.
AI Model — deleted #4959
01 · Connect apps

BYOK picker deleted — not later. The live row is #sec-5 / #sec-5b: MystFlo AI, paid per run, no key to set up, no caret, no own-key group.

Storage — the two values that aren't real yet
01 · Connect apps
Storage Google Sheets ▴
Where your bookings land
Connected ⌄
Live today
◉Google Sheet
Create a new one · Link a sheet I already have — see 5b
· Free
○Your Supabase · Free
Future values
⊘Airtable not a connected provider
Named as a roster source in booking specs, but no connect flow, no provider key, no code path. Drawn only so it isn't mistaken for a live option.
F3 — why these are Future, not Active
  • Neither state is drawable as Active without lying about the build. The Active picker is 5b; everything here needs code that does not exist. Both are drawn so the SHAPE is settled in advance — so the build has a contract to hit, not so it looks shippable.
  • AI Model picker = deleted (#4959 / ADR-037). Not a reopen. AiModelPicker.tsx has no provider dropdown and never will on this contract. MystFlo chooses the model. The Active row has no caret.
  • "MystFlo Storage" shipped (#3178, closed) — `STORAGE_PROVIDER_KEYS` now includes `mystflo_storage`, and it renders via its own zero-click component (`MystfloStorageRow.tsx`), not as an option inside THIS picker — an assistant's Storage row is either MystFlo Storage (zero-click, no expand) or an external file (this picker), never both at once. It's dropped from the list above for that reason, not a build gap. Known follow-up, not blocking: `MystfloStorageRow.tsx` still carries the pre-2026-08-04 `included` chip this contract retires.
  • Airtable is drawn as a NON-option deliberately. Assistant specs name it as a roster source (retreat booking's `roster_sources` accepts sheet | airtable | stripe), which makes it easy to assume it's a connectable Storage provider. It is not — there is no connect flow. Showing it struck-out here is cheaper than someone re-deriving that later.
  • Do not promote a row from F3 to 5b without the code landing first. The whole point of the Active/Future split on this file is that Part I is buildable-now.
Deferred (future, not whole-frame)
  • Real pre-activation chat sandbox — post-launch capability decision (needs a product call on cost + sandbox number).
  • Multi-instance comparison on Pulse — the seven-card wall handles it today.
  • Bulk actions across assistants (pause all, top up once) — deferred to a Pulse-level pass.
  • Deep run-level drill-down — lives behind “See every run →”, specified in the Pulse PRD.
  • `review_config` as a founder-visible surface — deliberately not drawn, stays invisible plumbing.
Overview› Personalize› Connect › Try
What this costs and when it runs
Price
One priceTiers ✓RangeFree
USD ⌄ one currency for this offering
Shared room
1,890
Private room
2,400
+ add a tier
When it runs
One dateDates ✓Recurring
Apr 12 → Apr 19, 2026 ✕ Oct 4 → Oct 11, 2026 ✕ + add another
my schedule isn't dates →
How long it lasts
7 nights, 8 days
Stored
Value
price.currency
USD
price.tiers[0]
Shared room · 1890
price.tiers[1]
Private room · 2400
price.display
from USD 1,890
dates[0]
2026-04-12 → 2026-04-19
dates[1]
2026-10-04 → 2026-10-11
duration
7 nights, 8 days
·· what the platform stores ··
Why these are controls and not text boxes (#3327)
  • A blank box can't tell a change from a re-format. "$1,890" → "$1890" is not a price change, but a string comparison says it is — and that is what makes the Brain's stale-listing flag untrustworthy (#3320). Structured entry removes the ambiguity where it is created rather than guessing at it later.
  • Currency is an ISO-4217 code, never a symbol (Peyton, BINDING 2026-08-10). USD / EUR / GBP / IDR. $ alone means USD, AUD, CAD, SGD or NZD — a symbol meaning five things cannot be compared, summed, or safely quoted to a customer in another market. ONE currency per offering; mixed-currency tiers are not a real case and are not drawn.
  • “From” is a rendering, not a field (Peyton, 2026-08-10). A founder writes “from $1,890” because there ARE several prices. Storing the summary and discarding the tiers loses the actual answer — so the shape selector holds tiers, and display is composed ONCE at save (from USD 1,890) and stored. It is never recomposed at render, so the D1 rule holds: no surface derives a price. The tiers underneath are what let an assistant answer “how much is the private room?”.
  • Dates are a LIST, because offerings recur. The Brain's own Bali example reads Apr 12–19 & Oct 4–11 — two occurrences. A single start→end row cannot hold it. Each occurrence is one date or a range; “+ add another” repeats it.
  • Duration is a separate question and already a separate field. Service.duration exists. “7 nights, 8 days” is how LONG it lasts, not WHEN it runs — a retreat has two occurrences and one duration. It never belongs in the date control.
  • Every control arrives pre-filled from the read. Site read, shared document, or a photographed brochure — the founder corrects, she never keys these in. An empty control here is a capture failure upstream, not a form to fill (Brain capture mandate, 2026-07-31).
  • The verbatim escape is not optional. “next cohort opens in Jan”, “every Tuesday”, “pay what you want” are real published values. Taking the escape stores the string alone and leaves the structured pair empty — a picker that could not express these would force founders to flatten real offerings.
Where this lands
  • Shape + rules: prd-pl-brain.md § “Structured value beside the written form”; acceptance AC-OFFVAL-01..08.
  • Brain-side twin of these controls: brain.html 28g (the offering correction editors). Same field types, same rules — this frame is the wizard's rendering of them.
  • First consumer: the stale-listing guard, #3320 (spec §3.4a — snapshot + three-rung comparison ladder).
  • 1ActiveExplore pre card — R1/R2/R3 card content · R13/R34 fixed-slot geometry · R15/R24/B1 app chips · R27 price.
  • 1bActiveShare the assistant — `ShareSheetModal` restyled to sheet chrome; R33 destinations locked to WhatsApp · X · Threads · Copy link.
  • 2ActiveTeam — Saved vs Permanent — pre/post boundary; D4 identity; A2 shared height baseline; R24 chips both sides.
  • 3ActivePre Overview — R5/R6 flow-steps chart, real sheet chrome; R26/R27 section order + price.
  • 4a · 4bActivePersonalize — phone + browser media — R32 preview fills the split; D-1 Brain Check deleted from 4a's form.
  • 4eActivePersonalize at 375 — R9/D2/C1 one mobile pattern; R23 keyboard/safe-area; D-1 Brain Check deleted here too.
  • 5ActiveConnect — R7/D-1 Brain Check's one home; R10 overflow; D3 wallet language; B2/B3 row grammar; R35 split doorway.
  • 5bActiveTwo standalone controls + one control species — pass 2 (2026-08-09) as amended by pass 3 (2026-08-10). Badge = WHICH apps are in play, ▾ only when ≥2 (Storage's 3 destinations, WAITL1's WhatsApp + Resend); single-app rows get no caret and no ⊘ coming-soon stub — unchanged by pass 3. Status button = T336 lifecycle verbs, chevron INSIDE the pill, present on EVERY connected row including AI Model; its menu is the only home for Disconnect / Reconnect / Switch account (T1164 retired into it). Impossible ⇒ greyed + explained, never removed (.off + always-visible reason line, no hover tooltip): Disconnect on ai_model, Reconnect while Pending, any row-level action on a ≥2-app row. Every app inside a picker carries the same button one tier down (.mini) — the Connected ✓ text + underlined Disconnect link pair is DELETED, and with it the pass-2 “Disconnect… → which-app MODE” hand-off; the badge owns “which app” at all times. Expired tokens still name their app collapsed. Connect on an unconnected pick → left co-edit slide sheet (shipped). Stack rule: one boundary at sm 640, every row. 375 + 640-pair + 768 + desktop tiers drawn.
  • 5dActiveBrain Check door → the REAL Book + Teach bar (#4714 wave 1, Peyton 2026-09-10) — Add / Edit in Brain → slides the real /brain/book in on the left (T1086 lock kept) with the docked bar; the peek rises inside the 40% pane (14d rule), never asks; the draft lands in the Book and Save to Brain confirms it (v5.27 unchanged) — closed before saving the row stays a blocker, "draft ready — Save to Brain" (NEW status). The focusSection co-edit pane is retired from this door (not deleted). 375 = stacked overlay, bar opens the full sheet in wave 1.
  • 6ActiveTry — R11 honest test by CTO matrix; B4 terminology; B7 derived read-back.
  • 7ActiveActivation, five outcomes — R12 pipeline; B5/B6 copy + link; D-3 Failed on rejected-template twin.
  • 8 · 8bActivePulse wall + ladder — R13/A4 geometry; A5 control row; R14/D4 identity; R15/R24/D3 chips + wallet; D-3 “Failed” everywhere.
  • 8cActiveNeeds your attention — one inbox, Band A (assistant cannot run) above Band B (one leftover). Health tile is operational (Needs you / N failed / — / All good), never a % while the inbox is open. Every Band A/B row + exclude + empty drawn. Status-driven. Pulse PRD §2.3a.
  • 8e · 8e-t · 8e-dActiveWallet-empty grace window (LOCKED by Peyton 2026-09-06) — chat assistants only: day 1–15 the issue sheet names the runway (“for 12 more days” + Day N of 15 track) and the card caption reads “Messages still reach you · 12 days left”; day 16+ the sheet lead becomes “Paused — new messages no longer reach you”, caption “New messages no longer reach you”. No customer-facing text in either state — grace is silent Slack relay + her own reply, step-down is silence. Status line, badge and amber are D-3 verbatim in BOTH states; the Needs-attention row is unchanged (one attention pattern). Connect-tab notice sub-line echoes the state. Data: backend-owned grace end + explicit relay state (never inferred client-side). Describes the TARGET relay (#4522) — today only the first message of a pause relays; no copy ships before #4522. Not built.
  • 9b · 9b-x · 9-mActivePulse tab — THE TEMPLATE, chat + exception fills (R37, 2026-09-03) — exception row (if any, D-5 stays TOP) → fixed four metrics(L) → the type's slot(R) → Recent activity(B), 5 rows + "See all ›", no in-tab pagination. R30 renamed/first/default; R17 rename; R19 “Reactivated”. Not built.
  • 8d · 8-rActiveRecords slot IN the Pulse card (Peyton 2026-09-02, R36) — the noun · count line is the card's last zone, collapses to zero on non-records cards, never for guests; tap deep-links ?assistant=<id>&records=open. Supersedes the under-card RecordsEntryRow. Not built.
  • 9b-r · 9-rActivePulse tab — BOOKING (records) fill, roster FIRST in the slot (R37, 2026-09-03 — supersedes the 2026-08-22/09-02 full-width-band placement) — ≤5 rows needs-verdict-first, "See all N ›" door, THEN the booking link/share/flyer under it; verdict set unchanged (Mark paid · Extend · Release); no lantern (D-5 owns it). Supersedes "Pulse ROW → full-screen destination" (#2924). Not built.
  • 9b-k · 9-k-mActivePulse tab — GENERATION (kit) fill (R37, 2026-09-03 — amends the 2026-08-22 generation-kit exception) — fixed four metrics like every other type + a piece-readiness slot with one "Open kit ›" door into the existing LaunchKitReviewSheetBody; the kit body no longer replaces the whole tab. Not built.
  • 9eActiveRecords sheet, nested over the Pulse tab (R36) — ModalWrapper sheet, nestedBackdrop + broadcastCloseAll=false, header-band title + subtitle + ✕, FilterChipGroup + PaginationBar idioms, every state (populated · empty · loading · warm-stale · cold error · signed-out · not-owner). Routed page + slide-over ban retired; deep link via URL param (name = CTO). 768 not drawn here (workshop-booking 13b). Not built.
  • 9fActiveActivity sheet, NEW, nested over the Pulse tab (R37, 2026-09-03) — the range chips + "‹ Newer · Page N of M · Older ›" pagination the tab's 5-row preview doesn't carry; populated · loading · empty states drawn. Not built.
  • 9cActivePost Personalize — the locked mirror (REDRAWN 2026-09-04, same day, #4432 Track 2 — supersedes the read-back ledger this cell used to describe) — same visual structure as pre-activation Configure (categories, .sm group headings, .field-label/.field/.opt-radio row anatomy), every field showing its saved state, nothing clickable on ANY row including Safe tier — no Edit, no per-row verb, no confirm dialog. The A6 Safe/Structural/Identity split (fieldEditPolicy.ts) stops driving display; a uniform .pz-locked wash is the only visual delta from an editable form. ONE top context line points to "Start fresh with a new assistant" (header ⋯ menu) as the only way to change anything — pausing unlocks nothing. AC-LIFECYCLE-11 needs a policy-level rewrite, not just wording.
  • 9gActivePost detail header — four lines, every type (2026-09-04, #4432; amends D-4) — L1 subject (program name / founder's word; falls back to the spelled-out type when there is no subject) · L2 spelled-out type + mono id · L3 status dot + label · price (plain text) · “live since <date>” · L4 activity only. Health leaves the header (Pulse tab Health row is its one home); trigger type moves to the Personalize tab's foot; the ⋯ menu carries Rename + Start fresh (Pause/Stop stay A5 icons). Root cause fixed at the source: auto-name is the subject alone (instanceNaming.ts), so the type word is never printed twice.
  • 9dActivePost Connect — Switch account in the STATUS menu — A6 amended 2026-08-09 (pass 2), refined 2026-08-10 (pass 3): the standalone button stays retired, and the action re-homes from the badge caret into the status button's menu — muted while Active (tap → pause-or-new-instance notice), live once Paused/Stopped. Badges on single-app roles carry no caret; their status chevrons stay. Two muted flavours, deliberately different: .dim = tappable, opens a reason WITH live paths (this frame's notice panel); .off = cannot act, purely informational reason on an inline line (5b). Reconnect stays available in every state; on a multi-app row Switch account greys out and points at the badge, same as Disconnect. Shipped 2026-08-17. Cropped, apps section only; mobile tier at 13d.
  • 10ActivePost Overview (was 3b) — R28 identical write-up pre/post; R30 tab set.
  • 11ActivePost Personalize (was 3c) — D-1 amends R29: Brain Check deleted, three per-run rows only.
  • 12Active“Waiting on you” (was 8c) — R31 pattern (WAITL1 only); A6 flag row; dry-run number field shipped; Meta gate shipped; no retry (by design).
  • 13 · 13bActiveReactivation — R18 dialog + CPO copy; R19 two sequences; “don't ask again” shipped.
  • 13c · 13d · 13gActiveLedger, Connect status menu, and the four-line header at 375 — mobile companions to 9c/9d/9g; 13c redrawn 2026-09-04 as the ledger (Active · Paused · row-open · confirm-as-sheet), 13g added for the header (subject · no-subject fallback · ⋯ menu). Phone shell per R6.
  • 14ActiveThe split — R35 three destinations (apps/funds/Brain), one `PageSlideOver` mechanic; D-1 Brain's only entry is Connect. 14c: Billing only from the Top-up card chip.
  • 14bActiveThe co-edit pane's states (2026-08-10) — the tier and the five moments frame 14 drew only at rest. Tier: the split engages at ≥1024 on every destination; 768–1023 and 375 get the same full-screen push (R35 note (d)'s “Mobile 375” wording is corrected to “below 1024”) — a 614px host pane would cross the 640 stack boundary and restack the wizard while she's away. States: loading (identity instant, provider form skeletons) · error (in the pane, at the field; host row reverts to its unconnected copy) · settle (host closes the split after a ~600ms tick — auto-close fires on job done, not connection succeeded, so a further provider choice keeps the pane open) · abandon (navigation, never cancellation; no confirm, typed secret discarded, in-flight request completes and the row flips itself) · OAuth return (wizard reopens from its own 24h draft on Connect, row ticked, pane does NOT reopen; the shipped “Continue Activation” banner demotes to fallback). Two rulings: the 40/60 axis does NOT mirror for Connect (no surface-specific exception), and the connect form is the pane's CONTENT, never a sheet inside it. SHIPPED — PageSlideOver has a live 'connects' case, ConnectsPage takes no focus prop, and ConnectionModal's body needs extracting to an inline form. Two questions left deliberately open: expired-draft / cross-device return, and whether a return that landed a further choice should reopen the pane.
  • 15ActiveBilling (was 10) — D4 identity, wallet language, app costs excluded.
  • F1FuturePersonalize — Document medium (formerly 4c) — P2 build contract, not yet built.
  • F2FuturePersonalize — Table medium (formerly 4d) — P2 build contract, not yet built.
  • F3MixedRole-row pickers — AI Model BYOK picker is deleted (#4959), not a reopen. Airtable is still named in specs as a roster source with no connect flow. MystFlo Storage shipped (#3178).
Locks D-1 · D-2 · D-3 · D-4 · D-5 · R33 · R34 · R35 — LOCKED by Peyton 2026-07-23 · A6 — LOCKED by Peyton 2026-08-02 · R36 — LOCKED by Peyton 2026-09-02
  • A6: edit-class gating — Safe fields (payment-ask wording, reminder phrasing, booking keywords, voice descriptors) editable while Active. Structural fields (WhatsApp message-template content, connected WhatsApp/Stripe account, payment link/setup, schedule, add-ons) locked while Active — “Pause to change”, unlock on Pause. Identity fields (workshop/offering name, event dates, deposit arrangement) never edit in place — Start-fresh pointer only, in every state. A6 amended 2026-08-06, re-homed 2026-08-09, refined 2026-08-10: the account-switch is a STATUS-MENU item (not a badge caret) — muted-but-tappable while Active, live once Paused/Stopped; Reconnect stays available always. See frames 9c/9d/13c/13d — shipped 2026-08-17 (`fieldEditPolicy.ts` + status-menu mute).
  • D-1: Connect owns the Brain Check as its only home; Personalize is per-run knobs only (greeting, handling rules), Brain values prefilled, no readiness gate.
  • D-2: mobile preview = Variant A (slide-up), the only pattern — Variant B removed (C1).
  • D-3: status ladder + wallet language — amber wallet-empty, red reserved for Failed (replaces “Needs a fix”).
  • D-3 — second amendment (LOCKED by Peyton 2026-09-06, frame 8e): the status/meta line stays verbatim and amber in every wallet-empty state, including the day-16 step-down. The footer caption gains a third branch for chat assistants on wallet_empty — “Messages still reach you · N days left” while relaying, “New messages no longer reach you” once stopped — beside the #4516 “Nothing lost” shared branch. No customer-facing message exists in either state. Mirrored into assistant-summary-card.md self-check item 25. Ships only with #4522.
  • D-4: identity flip — instance name + id lead, template name steps down.
  • 2026-09-04 (Peyton, Option B — #4432 Track 2): A6 presentation first amended to a read-back ledger (label → value, Edit on Safe rows) — SUPERSEDED the same afternoon: Peyton reversed it to a locked mirror of pre-activation Configure with nothing clickable on any row (frames 9c / 13c / 768 tier, current). D-4 amended — the post header is the four-line hierarchy (frames 9g / 13g): subject · spelled-out type + id · status · price · live since · activity; template word once, health never in the header.
  • D-5: post modal's Pulse tab hosts the pending-review item at top, deep-linking to the owning tab.
  • R33: share destinations locked to WhatsApp · X · Threads · Copy link.
  • R34: pre-card anatomy is fixed-slot — contexts swap slot content, never slot existence.
  • R35: the split generalizes to three destinations (apps/funds/Brain), one `PageSlideOver` mechanic — nested `ConnectionModal` retired on the Reconnect path; tap funds opens Top-up (amount + card chip), never Billing; Billing slides in only from that chip (14c); live-row-update promise extends to all three; mobile stays one full-screen push pattern.
  • R36 (Peyton 2026-09-02): records surfaces live INSIDE the existing Pulse tab (a noun-titled block between metrics and activity) plus a nested, scrollable records sheet stacked over it; the Pulse card carries the entry as an in-card slot, never a sibling row under the card; the routed /pulse/:id/records page is retired into a redirect; deep-link via a URL param on the sheet (?assistant=<id>&records=open — name = build decision, CTO). Supersedes #2924's route lock and the records-surface PageSlideOver/slide-over ban; R30/R31 stand (four tabs, flag-row on the card). Frames 8d · 9b-r · 9e.
  • R37 (Peyton 2026-09-03 — "streamline the assistant-detail Pulse tab … 2 column + 1 row … any change to the lifecycle master applies to all assistants; type-specific parts become components in the master that the individual files refine"): the Pulse tab is ONE template — left column is the fixed four universal numbers (Runs · Health · Last run · Cost MTD, + one optional appended outcome row), right column is THIS type's slot (chat share row · records roster-then-booking-link · generation piece-readiness preview), bottom is the universal activity ledger (5 rows + one "See all ›" door). Both doors — the roster's "See all N ›" and the activity's "See all ›" — are full-width nested slide-up sheets (contentWidth="wide", nestedBackdrop, broadcastCloseAll={false}): the records sheet (9e, unchanged) and the NEW Activity sheet (9f), which now owns the range chips + ‹ Newer · Page N of M · Older › pagination that no longer render on the tab itself. Amends R36's placement: the records roster is the RIGHT SLOT's first item, not a full-width band between the metrics/quick-actions pair and activity. Amends the 2026-08-22 "generation-kit keeps its own full-body review sheet" exception — generation is now a typed slot (piece-readiness + "Open kit ›") like every other type, not a whole-tab swap. 375 stays one column, same order: exception → metrics → slot → activity. Assistant files never redraw this tab — they carry a .revisit card to the matching master frame + a short slot-delta list. Frames: 9b (chat) · 9b-x (exception) · 9b-r (records) · 9b-k (generation) · 9e (records sheet, unchanged) · 9f (NEW Activity sheet).

Mirrored into kit `design-decisions.md` + archetypes: `assistant-detail-tabs.md`, `assistant-summary-card.md`, `pulse-surface.md`.