WiseAI Realtor — Calendar & Tasks Expected Output Spec
⛔ STATUS: DRAFT — NOT APPROVED. CLAUDE.md Rule #17 (HARD GATE) is NOT satisfied.
Stage-1 agent research, pre-populated from the realtor design docs + the
calendar-tasks.htmlmock (and thereviews-automations.htmlAutomations tab for the drip library). Do not build the customer-facing screen until the founder approves and confirms the open items in a Stage-2 interview.
Sourced from (read-only, 2026-06-29):
data-model.md§1.8 (re_tasks,re_action_plans/re_action_plan_steps),ai-guardrails.md(RULE 5 escalation + language routing; RULE 6 autopilot bounds),backend-completeness-audit.md(speed-to-lead SLA, routing, showing scheduler "named, not designed"),design-direction.md(Follow-Up Coach, autopilot),realtor-mockups/calendar-tasks.html, andrealtor-mockups/reviews-automations.html(Automations/drip library).
0. Scope — what this spec covers, and what it does NOT
This spec covers Calendar & Tasks — the week/day/list calendar, the
Follow-Up-Coach task rail (Overdue / Today / Upcoming), the drip /
action-plan library that spawns tasks, the speed-to-lead SLA timer + hot-lead
alert, and lead assignment/routing. Sibling of realtor-dashboard-mvp.md
(the dashboard's "Call these 5 today" reads the same re_tasks), realtor-deals-mvp.md
(deal key-dates surface as reminders here), and realtor-notifications-mvp.md
(the alert delivery layer).
Does NOT cover: the Reviews engine + the Automations builder UI surface in
detail (Reviews is acceptance/reviews-engine-mvp.md; the Automations tab
of reviews-automations.html is referenced here only as the action-plan library
that feeds re_tasks, and may warrant its own spec — flag); the conversation
inbox (realtor-inbox-mvp.md); the live AI capture behaviour (ai-front-desk.md).
Build posture: NEW. Evolves the existing local_business_followup_tasks
(lead-only, free-text) into re_tasks (contact/deal-aware, real ownership —
data-model.md §1.8). Reads the proposed re_* spine (migrate-before-use).
1. The mock screen this spec governs + what it reads
Governs: realtor-mockups/calendar-tasks.html — a week calendar (Week/Day/
List switch) with an all-day key-dates strip (condition due, closing,
birthday), an hour grid with typed events (Showing / Open house / Listing
pres. / AI-booked / Call-back / Closing — color-legend), a "now" line, a
pending showing-request → Confirm/Decline affordance, and a right Task rail
(Overdue / Today / Upcoming) where each task carries a reason + a Follow-Up
Coach / "From deal · key date" tag + one-tap Call/Text/Email and (for the
showing request) a Confirm/Reschedule control. Toolbar shows "Synced · Google
Calendar + Cal.com" and "Aria books only inside your hours".
Plus the Automations / drip library (reviews-automations.html →
Automations tab): 9 sequences (Buyer nurture, Seller valuation, New-lead
speed-to-lead, Open-house follow-up, Past-client keep-in-touch, FSBO, Expired,
Investor, Newcomer) with steps (Email/SMS/Task/Guide) + a consent gate.
Reads (target-state CRM-spine APIs — WS3; verify exact route names; do not fabricate):
| Surface | Underlying read |
|---|---|
| Task rail (Overdue/Today/Upcoming) | re_tasks (status, due_at, assigned_agent_id, type) — role-scoped |
| Task reason / source tags | re_tasks.created_by (ai_coach/system/agent) + action_plan_step_id + deal link |
| Calendar events | showings/open-houses/listing-pres/call-backs (tasks + appointments); key dates from re_deals + re_contacts (birthday/anniversary) |
| Showing request | a captured request (re_tasks type=showing, status=open) pending agent confirm (§4.4) |
| Speed-to-lead | re_interactions (first inbound occurred_at vs first outbound) |
| Drip/action-plan library | re_action_plans + re_action_plan_steps; enrolling a contact spawns re_tasks |
| Routing | re_contacts.assigned_agent_id driven by routing config over local_business_agents |
Demo tenant: Terry & Sheri Real Estate (…0c01). Mock content is demo;
NEVER a real customer (feedback_never_modify_customer_data).
2. The AI-Bridge / honesty anchor
- Aria proposes; the agent acts. Follow-Up-Coach tasks are AI-suggested with a reason ("Viewed 14 Riddell 4× · no reply 2 days — re-engage"); they are the agent's to-do, not autonomous client contact. A task that would contact a client only fires a send when permitted (consent + the SMS gate, §6).
- Suppression gates every task action. No task surfaces a Call/Text/Email
affordance against a
do_not_contactcontact or a withdrawn/expired channel (re_contactsconsent rollup;ai-guardrails.md).
3. Role-based visibility
| Bucket | Roles | Scope |
|---|---|---|
| Brokerage management | brokerage_owner, broker_admin (brokerage scope) | All agents' calendars/tasks across the brokerage; assign/route; SLA view |
| Team management | team_admin (team scope) | The team's calendars/tasks; assign/route within team; team SLA view |
| Agent / ISA | agent, isa (own scope) | Own calendar + assigned tasks + claimable pond; not a peer's private calendar |
| Support / external | transaction_coordinator, marketing_assistant, external_partner (bounded) | Scoped/read-only (transaction_coordinator sees deal tasks + team-read); external_partner read-only |
4. Expected outputs
4.1 — Calendar (week/day/list) + key dates
Should see:
- A week grid (default), Day and List alternates, with typed, color-legended events and a live now line; an all-day strip for key dates (deal condition deadlines, closings, client birthdays/anniversaries).
- Events read from tasks/appointments +
re_dealskey dates +re_contactsrelationship dates; clicking an event opens its detail/linked record.
Should NOT see:
- Events labelled "booked by Aria" presented as confirmed AI bookings (§4.4 / §6 — reframe to captured request + agent confirm).
- A two-way Google/Cal.com sync claimed as live when it is read-only/not built (§4.4 OPEN).
Success: the agent sees their week — showings, open houses, listing presentations, call-backs, and deal deadlines — in one place.
4.2 — Follow-Up-Coach task rail (Overdue / Today / Upcoming)
Should see:
- Tasks grouped Overdue / Today / Upcoming, each with a title, a reason, a source tag (Follow-Up Coach / "From deal · key date" / Open house), a language chip where relevant, an overdue badge, and one-tap Call/Text/Email.
- The set is role-scoped (agent sees own; management sees team) and excludes suppressed contacts from any send/call affordance.
- Completing a task is optimistic; it writes a
re_interaction(actor=human) where it represents a touch.
Should NOT see:
- A generic count with no reasoning (the value is why + who + next).
- A Call/Text/Email enabled against a
do_not_contactcontact.
Success: the rail gives a defensible, reasoned daily call/follow-up list that matches the dashboard's "Call these 5 today".
4.3 — Drip / action-plan library (spawns tasks; consent-gated; no cron send)
Should see:
- A library of action-plan/drip sequences (Buyer nurture, Seller valuation, New-lead speed-to-lead, Open-house follow-up, Past-client keep-in-touch, FSBO, Expired, Investor, Newcomer), each with step count + channels + enrolled count, toggled on/off. A sequence builder (trigger → wait → email/SMS/task) with a consent gate.
- Enrolling a contact spawns
re_tasks(and, for send steps, drafts that a human presses — never an unattended send). Template steps can be global (re_action_plans.business_id NULL) and cloned per tenant. - A persistent banner: "Drips respect global suppression & consent … no cron auto-sends to prospects."
Should NOT see (HARD):
- Any cron / unattended send of a drip step to a prospect
(
feedback_never_cron_send_campaigns); a human presses every send to a real person (feedback_db_writes_ok_sends_need_blessing). - A drip step contacting a suppressed/withdrawn contact (consent re-checked before each step).
- SMS drip steps live by default. ⚠️ The mock shows SMS steps enabled (Buyer nurture, New-lead, Open-house). Per the batch directive, SMS is OFF by default + consent-gated until the founder confirms SMS-in-scope — flag, ship SMS steps disabled.
Success: an agent enrolls a contact in "Buyer nurture" and the right tasks appear, with every client-facing send awaiting a human press and suppression honored.
4.4 — Showing handling: REQUEST capture + agent confirm (NOT AI booking)
⚠️ CARRIED-FORWARD INCONSISTENCY — flagged, not silently resolved. The
calendar-tasks.htmlmock shows "🤖 booked by Aria" events, "Aria books only inside your hours", and "Synced · Google Calendar + Cal.com". But the approvedai-front-desk.mddecision 4 is capture + FAQ + escalate ONLY — the AI does NOT book/schedule, and the audit lists the Cal/Google showing scheduler as "named, not designed" (not built). Spec the buildable MVP:
Should see (MVP — the buildable path):
- A showing request the AI captured surfaces as a pending request (calendar: dashed "Showing request · awaiting you" with Confirm/Decline; task rail: "Confirm Sun 2:00pm showing · …" with Confirm/Reschedule). The agent confirms → it becomes a confirmed event. This request-capture + human-confirm loop IS in the mock and IS buildable now.
- A read-only/availability display of the agent's Google/Cal.com calendar is acceptable (so the AI/agent see conflicts), if a connection exists.
Should NOT see / OPEN (flag, do not build silently):
- The AI autonomously confirming a calendar slot ("🤖 booked by Aria" as a done booking) — relabel to "showing request captured by Aria · awaiting your confirmation". Autonomous booking + two-way Cal/Google write-sync is OPEN pending (a) a scheduler being designed/built and (b) a founder decision on whether the AI may auto-confirm within set hours. Until then: capture + agent-confirm only.
Success: an AI-captured showing request lands as a one-tap-confirm item; no calendar slot is presented as AI-confirmed until the scheduler + founder decision land.
4.5 — Speed-to-lead SLA timer + hot-lead alert + routing
Should see:
- A speed-to-lead signal: first-response time per new lead
(
re_interactions), an SLA timer, and an unactioned-lead surface ("N leads unactioned > 24h"). The hot-lead alert is make-or-break (audit) and is delivered via Notifications (realtor-notifications-mvp.md). - Lead assignment/routing: round-robin / claim / pond / geo / language-based
between agents (Beckett's two agents). Language routing derives from
local_business_agents.languages[]∩re_contacts.preferred_language— a language is NEVER hardcoded (same rule as the Smart-List language rule,realtor-leads-mvp.md§4.3). Routing setsre_contacts.assigned_agent_id.
Should NOT see:
- A hardcoded language-routing rule shipped to every tenant.
- An SLA/hot-lead path that auto-sends to the lead without a human (the alert goes to the agent; the outreach is the human's, or a consent-gated drip §4.3).
Success: new leads route to the right (often language-matched) agent, the SLA timer + unactioned surface make speed-to-lead visible, and the hot-lead alert reaches the agent fast.
5. Empty / loading / error states
| State | Expected output |
|---|---|
| No tasks/events | Demo-seeded preview + onboarding nudge ("Tasks from your AI front office and your deals will appear here") — never blank (anti-pattern #6). |
| Loading | Calendar + rail skeletons, not a spinner (anti-pattern #7); optimistic on complete/confirm. |
| Calendar not connected | Honest "Connect Google Calendar / Cal.com to see availability" — not a fake "Synced" badge; the request-capture + confirm path still works without it. |
| Read/complete error | Inline "Couldn't update — retry"; the task reverts. |
| Suppressed contact | Task action (Call/Text/Email) disabled with the reason. |
6. Carried-forward constraints (consistent across the batch)
- Aria does NOT book/schedule → request-capture + agent-confirm only; auto-booking + two-way Cal/Google sync is OPEN (§4.4).
- SMS consent-gated + OFF by default (no unattended sender); drips never
cron-send to prospects; crisis/safety NEVER gated (
ai-guardrails.md). - Role enum (rbac.ts — implemented source of truth): agent | team_admin | transaction_coordinator | broker_admin | brokerage_owner | marketing_assistant | isa | external_partner (scopes own|team|brokerage); management vs agent scope.
- No realtor pricing — gate by role/module.
- Honest metrics only; "Not measured" when unknown. Language never hardcoded.
7. Accessibility (AODA → WCAG 2.1 AA)
- Calendar: grid is keyboard-navigable; events are buttons with accessible names (title + time + type, not color alone); the "now" line + key-date strip have text equivalents; reduced-motion honored.
- Task rail: real list semantics; checkboxes for done; Confirm/Reschedule are labelled buttons; overdue/Today/Upcoming convey by text, not color alone.
- Drip toggles: labelled switches with state; "consent required" is text.
- Contrast: ≥4.5:1; gold accent only; teal actions meet AA.
8. Acceptance checklist (QA runs on the deployed URL)
Behavioural verification on wiseaiagency.com (real host) against the demo
tenant (…0c01); never "build passes". Sample at ≥2 timepoints.
// Calendar + tasks
test.fixme('Week/Day/List calendar renders typed events + all-day key dates; events open their linked record', () => {});
test.fixme('Follow-Up-Coach rail groups Overdue/Today/Upcoming, each task WITH a reason + source tag', () => {});
test.fixme('task Call/Text/Email is DISABLED for do_not_contact contacts; completing a task is optimistic', () => {});
// Showings — request capture, NOT AI booking
test.fixme('an AI-captured showing surfaces as a REQUEST with Confirm/Decline; only agent confirm makes it an event', () => {});
test.fixme('no calendar slot is shown as AI-confirmed ("booked by Aria"); auto-book + 2-way Cal/Google sync flagged OPEN', () => {});
// Drips / action plans
test.fixme('enrolling a contact in an action plan spawns re_tasks; client-facing sends await a human press', () => {});
test.fixme('NO cron/unattended drip send to a prospect; suppression re-checked before each step', () => {});
test.fixme('SMS drip steps are OFF by default + consent-gated until SMS-in-scope is confirmed', () => {});
// Speed-to-lead + routing
test.fixme('speed-to-lead timer + "unactioned > 24h" surface render from re_interactions', () => {});
test.fixme('language-based routing derives from agent languages ∩ lead preferred_language — never hardcoded', () => {});
test.fixme('hot-lead alert reaches the assigned agent (delivered via Notifications), not an auto-send to the lead', () => {});
// States + a11y
test.fixme('empty/loading/not-connected/error states render per §5; never blank, never a spinner, no fake "Synced"', () => {});
test.fixme('calendar + rail are keyboard-navigable; events/tasks convey meaning by text; reduced-motion honored', () => {});
9. Guardrails for agents building against this spec
- Rule #17 not satisfied — do not build until founder approval.
- Request-capture + agent-confirm for showings — the AI never confirms a slot; relabel every "booked by Aria"; gate auto-book + two-way sync (OPEN).
- No cron sends; SMS off-by-default + consent-gated; crisis never gated.
- Language routing is per-agent, never hardcoded.
- Migrate-before-use —
re_tasks/re_action_plans/re_action_plan_stepsare proposals; verify columns viainformation_schema(Rule #18); founder-gated DDL; evolvelocal_business_followup_tasksadditively. - Honest metrics; verify on the real host; behaviour not DOM presence; evidence-or-nothing.
- If code diverges, update the spec first (founder approval), then the code.
End of spec. STATUS: DRAFT — NOT APPROVED. Open items for Stage-2: (1) whether the AI may ever auto-confirm a showing within set hours (and the scheduler that requires); (2) two-way Cal/Google sync scope; (3) the routing default (round-robin vs claim vs language-first) for the Beckett 2-agent team; (4) whether the Automations builder UI needs its own acceptance spec.