Skip to main content

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.html mock (and the reviews-automations.html Automations 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, and realtor-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):

SurfaceUnderlying read
Task rail (Overdue/Today/Upcoming)re_tasks (status, due_at, assigned_agent_id, type) — role-scoped
Task reason / source tagsre_tasks.created_by (ai_coach/system/agent) + action_plan_step_id + deal link
Calendar eventsshowings/open-houses/listing-pres/call-backs (tasks + appointments); key dates from re_deals + re_contacts (birthday/anniversary)
Showing requesta captured request (re_tasks type=showing, status=open) pending agent confirm (§4.4)
Speed-to-leadre_interactions (first inbound occurred_at vs first outbound)
Drip/action-plan libraryre_action_plans + re_action_plan_steps; enrolling a contact spawns re_tasks
Routingre_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_contact contact or a withdrawn/expired channel (re_contacts consent rollup; ai-guardrails.md).

3. Role-based visibility

BucketRolesScope
Brokerage managementbrokerage_owner, broker_admin (brokerage scope)All agents' calendars/tasks across the brokerage; assign/route; SLA view
Team managementteam_admin (team scope)The team's calendars/tasks; assign/route within team; team SLA view
Agent / ISAagent, isa (own scope)Own calendar + assigned tasks + claimable pond; not a peer's private calendar
Support / externaltransaction_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_deals key dates + re_contacts relationship 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_contact contact.

Success: the rail gives a defensible, reasoned daily call/follow-up list that matches the dashboard's "Call these 5 today".


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.html mock shows "🤖 booked by Aria" events, "Aria books only inside your hours", and "Synced · Google Calendar + Cal.com". But the approved ai-front-desk.md decision 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 sets re_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

StateExpected output
No tasks/eventsDemo-seeded preview + onboarding nudge ("Tasks from your AI front office and your deals will appear here") — never blank (anti-pattern #6).
LoadingCalendar + rail skeletons, not a spinner (anti-pattern #7); optimistic on complete/confirm.
Calendar not connectedHonest "Connect Google Calendar / Cal.com to see availability" — not a fake "Synced" badge; the request-capture + confirm path still works without it.
Read/complete errorInline "Couldn't update — retry"; the task reverts.
Suppressed contactTask 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-usere_tasks/re_action_plans/re_action_plan_steps are proposals; verify columns via information_schema (Rule #18); founder-gated DDL; evolve local_business_followup_tasks additively.
  • 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.