Every message Clara or our system sends to people outside PropFlow, checked for engineering text, jargon and promises we don't keep, with the plain-English replacement for each.
2026-09-30 · main as of 13:17 MT · Proposed, pending review · wording and source fixes only
1. TL;DR · 2. Messages by audience (renters, residents, client staff, vendors) · 3. Proposed PRs · 4. Method
The rule: every message a customer gets is an outcome Clara produced, a hand-off to a person, or “I took a message, here it is.” On any failure Clara says nothing and engineering is paged.
Many send points repeat the same message, so the 79 rows below stand for the 156 flagged send points. The worst cases are the ones that reach renters and residents when something breaks: a reply stitched from internal notes, an office number that rings back to Clara, a “checking on that” that never gets followed up. Those are all in open PRs today.
Quotes are shortened. Curly braces mark a filled-in value. “Interpretation” means read from code, not seen in a real message.
| What triggers it | Channel | What it says today | Problem | Proposed wording | Status | Where in code |
|---|---|---|---|---|---|---|
| Clara's reply fails after she already did something (booked, noted, sent) | Text, email | A reply stitched from internal action notes, e.g. “Tour booked (tool: book_tour)…” | error text | One plain line about what got done (“You're booked for Tuesday at 3pm.”), or nothing. Engineering is paged. | Open #14348 | fail-open-fallback-reply.ts: buildFailOpenReply |
| Clara can't produce a reply at all | Text | “…please call the office at {office phone}” | wrong promise | Nothing is sent. Engineering is paged. (The office number can ring straight back to Clara.) | Open #14348 | conversation-manager.ts: noResponseFallbackReply |
| A reply had private details removed | Text, email | “[REDACTED]” inside the message | internal id or code | Clara writes the reply again once without it; if that fails, nothing is sent. | Open #14348 | conversation-manager.ts: redaction step |
| Someone texts “reset” | Text | The conversation is wiped for any sender | error text | Only test phones can reset. Real people get a normal reply. | Open #14348 | inbound-dispatcher.ts: reset command |
| Clara says a tour is booked when the booking failed | Text, email | “You're all set for {time}…” | wrong promise | Confirmation only after the calendar booking succeeds; otherwise Clara retries and offers another time. | Open #14353 | tour booking reply path |
| Clara's reply needs a second look before sending | Text, email | “Let me check on that and get right back to you.” (nothing follows) | wrong promise | Nothing is sent on text or email. The phone keeps the line, since silence on a call is worse. | Built, no PR fede/no-holding-line-on-error (parked, not pushed) | anomaly-review-gate.ts, voice-review-gate.ts |
| Clara's fact-check step rejects a reply | Text | “I'm looping in your property manager…”, and the reply held with no follow-up | wrong promise | The fact-check step is removed; Clara's normal reply goes out. | Built, no PR fede/remove-hallucination-guard (no PR yet) | conversation-manager.ts: fact-check fallback |
| Clara's reply leaked her own instructions and was cleaned | Text, email | “Hey there! I'm Clara — what can I help you with?” (mid-conversation) | wrong promise | Nothing is sent. Engineering is paged. | Not started group G11 | internal-prompt-strip.ts: SAFE_FALLBACK |
| A policy check fires after Clara already replied | Text | “I want to correct something I just said: this hasn't actually reached the property team yet…” | error text | Nothing is sent to the person. Engineering is paged and the team gets the message. | Not started group G11 | conversation-manager.ts: policy correction (~14440) |
| A real person's number looks like a test number | Text | “This number is reserved for testing. Please use the test property.” | error text | Treat them as a normal person. Only our own test phones get test handling. | Not started group G11 | inbound-dispatcher.ts: test-sender check |
| A message is parked for the team | Text | A placeholder acknowledgement with internal wording | jargon | “Got it. I've passed this to the team and they'll get back to you.” | Not started group G11 | parked-reply acknowledgement |
| Any message that prints an address | Text, email | Addresses like “12 Main St, , , ” when parts are missing | error text | Skip empty parts: “12 Main St, Denver”. | Not started group G11 | agents/clara/lib/address-utils.ts: formatAddress |
| Someone texts HELP | Text | “Clara AI - Property Management Assistant. Reply STOP to opt out.…” | jargon | “This is Clara, the assistant for {property}. Reply STOP to stop texts. For an emergency, call 911.” | Not started group G11 | twilio/webhook/route.ts: HELP reply |
| Someone emails in and the reply is from us | Subject “Re: {Clara's internal one-line summary}” | internal id or code | “Re: your message to {property}” | Open #14337 | relay email subject builder | |
| Identity check fails mid-reply | Text | Raw error handed to Clara, which could repeat it | error text | Clara never sees the raw error; she answers normally or stays silent. | Open #14337 | shared identity-mismatch error |
| Tour calendar invite attachment | File named with an internal id, e.g. tour-8f3c….ics | internal id or code | tour-{property}-{date}.ics | Open #14344 | tour invite .ics builder | |
| A call comes in and our phone handler fails | Phone | “We're sorry, we're experiencing technical difficulties with our maintenance line.” (said on leasing calls too) | error text | “Sorry, we can't take your call right now. Please try again in a few minutes, or text us at this number.” | Not started group G10 | twilio/voice/incoming/route.ts: error TwiML |
| A transfer can't be placed | Phone | “Sorry, we could not connect you. Please call back and we will take your message.” then hangs up | wrong promise | Take the message now: “Nobody's free to pick up right now. Leave your name, number, and what you need after the tone, and we'll call you back.” | Not started group G10 | hunt-chain.ts: unplaceable transfer |
| The transfer webhook crashes | Phone | The phone carrier's stock “an application error has occurred” (interpretation, not heard live) | error text | Same message-taking line as above. | Not started group G10 | voice/hunt/route.ts: handler |
| One of Clara's phone tools fails | Phone | Tool result text “Internal server error”, “INVALID_INPUT”, “Unknown tool” that Clara may read out | error text | The tool tells Clara in plain words what to do: “That didn't go through. Take their name and number and tell them the team will call back.” | Not started group G10 | voice tools routes: error results |
| Availability lookup fails on a call | Phone | “…let me have the team follow up with you today on what's open” | wrong promise | “I can't pull up what's open right now. Can I take your name and number so the team can send it to you?” | Not started group G10 | voice-agents/leasing.ts: availability error line |
| What triggers it | Channel | What it says today | Problem | Proposed wording | Status | Where in code |
|---|---|---|---|---|---|---|
| A repair is closed; Clara asks for a rating | Text | “Hey {name}, your maintenance ticket is complete — how would you rate the experience?” | jargon | “Hi {name}, your repair is done. How did it go? Reply 1 to 5.” | Not started group G2 | rating.ts: rating prompt |
| A resident sends any rating | Text | “Thanks, {name}! Glad we could help.” (also after a 1) | wrong promise | 4 or 5: “Thanks, {name}! Glad it's sorted.” 1 to 3: “Thanks for letting us know, {name}. I've passed this along to the team.” | Not started group G2 | rating.ts: rating reply |
| A resident reports a gas or carbon monoxide smell | Text | “This could be a gas emergency… Your property manager has been paged.” (same wording for carbon monoxide) | jargon | Gas: “…I've let your property manager know right away.” Carbon monoxide: “This could be carbon monoxide. Get everyone outside to fresh air now and call 911. I've let your property manager know right away.” | Not started group G9 | inbound-dispatcher.ts: life-safety reply |
| A resident texts their email address | Text | “Got it — we'll send your renewal paperwork to {email}.” (even when nothing is being renewed) | wrong promise | “Got it — I've saved {email} for your account.” | Not started group G3 | handle-tenant-email-capture.ts |
| A resident says they are moving out | Text | “…It's not official until you file Notice to Vacate in the resident portal…” | jargon | “To make it official, please submit your notice to move out in the resident portal: {link}.” | Not started group G3 | renewal-reminder-sms.ts: move-out reply |
| Lease-end reminder, 15 days out | Text | “…ends {date} — about two weeks away.” (also sent when the real gap is different) | wrong promise | “…ends {date}.” (no rounded countdown) | Not started group G3 | renewal-reminder-sms.ts: milestone copy |
| Lease-end reminder with no end date on file | Text | “…ends your lease end date”, or “Invalid Date” | error text | “Your lease is ending soon.” | Not started group G3 | renewal-reminder-sms.ts, recap-sms.ts |
| Renewal offer with no rent on file | Text | “$0/mo” or “$NaN” | error text | Do not send. The team sees the missing rent on the renewals page. | Not started group G3 | renewal handlers.ts, renewal-auto-start.ts |
| Past-due balance reminder | Text | “Hi{name}, this is {property}.” where name can be a placeholder like “Resident” | jargon | “Hi there,” when the name is a placeholder. | Not started group G3 | collections-chase-copy.ts: greeting |
| Renewal phone call, no price set | Phone | Clara told “standard renewal pricing” and may repeat it | jargon | “The team will send you the renewal price.” | Not started group G3 | renewal-call-context.ts |
| A resident calls the repair line | Phone | “I can take care of work orders and troubleshooting right now…” | jargon | “I can put in a repair request or help you troubleshoot right now, or get you to a person.” | Not started group G10 | voice-agents/maintenance-tenant.ts: greeting |
| A resident asks for a repair on a leasing-only line | Text | “I'm sorry — we're not able to take maintenance or repair requests on this line…” (also sent to technicians) | wrong promise | Residents: “For repairs, please use {repair number or portal}.” Technicians never get this line. | Not started group G2 | fail-open-fallback-reply.ts: MAINTENANCE_NOT_HANDLED |
| Repair-update message fails to build | Text | Generic fallback text | error text | Nothing is sent. Engineering is paged. | Not started group G2 | maintenance-comms fallbacks (~537, ~829) |
| What triggers it | Channel | What it says today | Problem | Proposed wording | Status | Where in code |
|---|---|---|---|---|---|---|
| A new inquiry can't be recorded in AppFolio | “Guest card not created…” with the technical reason | error text | Goes to our engineering alert channel, not the client. | Fixed #14252 merged today | guest-card failure notice | |
| First email held, or a reply didn't deliver | Internal hold and delivery notices | error text | Go to our own inbox only. | Fixed #13343 merged | held-email and undelivered notices | |
| One of Clara's actions is rejected | Rejection reason from the tool | error text | Goes to our alert channel only. | Fixed earlier, on main | tool rejection notice | |
| Clara's fact-check step flags a reply | Email, text | The internal review note, pasted to the team | error text | Removed with the fact-check step; nothing goes to the team. | Built, no PR fede/guard-block-no-internal-text-to-staff, fede/remove-hallucination-guard | conversation-manager.ts (~13057, ~13130, ~13253) |
| Clara promised something nobody is following up on | Subject “Clara made a promise nobody's following up on”; body “(no inbound message on file)” | jargon | Subject: “A caller needs a follow-up — {property}”. Leave out the quote when there isn't one. | Not started group G5 | pm-delivery.ts, promise-backing-policy.ts | |
| Email subjects with tags | “[PropFlow URGENT]”, “[Renewal escalation]”, “[VIRTUAL TOUR]” | jargon | “Urgent:”, “Renewal needs your review:”, “Virtual tour:”; no tag at all otherwise. | Open #14337 | notice subject builders | |
| Possible gas leak page to the manager | Tagged subject and internal phrasing | jargon | “Possible gas emergency at {property} — please call the resident now” | Open #14344 | gas page email | |
| A caller hung up before being reached back | Email, text | Internal status words in the notice | jargon | Plain description of who called and what they need. | Open #14344 (email), #14342 (text) | stale dial notice |
| Clara couldn't do what was asked | Raw decline reason codes | internal id or code | A plain sentence per reason. | Open #14344 | humanizeDeclineReason, plainUnfulfillableSummary | |
| Tour booked, changed, or on the day | Text | “Tour #1234… Reply 1 to… 2 to…” | internal id or code | “Heads up: Riley B.'s tour at {property} is confirmed for Tue 3pm.” No number, no menu. | Open #14342 (overlaps #13883: merge one, close the other) | staff tour texts |
| Any staff notice with no property matched | “Property: not identified yet” | jargon | Leave the line out. | Not started group G5 | notices/shared.ts: property line | |
| Someone asks for a person | Text | “Hand-off: {who} asked for a person about… — full details in your email.” | jargon | “{who} asked to talk to someone about {topic} at {address}. The details are in your email.” | Not started group G5 | staff-notice-sms-text.ts |
| Phone rings a staff member (text heads-up) | Text | Role printed as a code, e.g. “prospect”, “tenant” | internal id or code | “Jane Doe is calling about renting” / “…a resident” / “…a vendor” | Not started group G5 | text-on-ring.ts: role label |
| Phone rings a staff member (spoken whisper) | Phone | “{name}, {role code}” | internal id or code | Same plain role words as the text. | Not started group G5 | hunt-chain.ts: huntWhisperWho |
| A caller was never matched to a record | “(not matched to a record)” | jargon | “New caller” | Not started group G5 | missed-call-note.ts | |
| After a transferred call | “(the transcript is empty…)”, “not a new incident” | error text | Leave out the transcript section when empty; say “Same issue they called about before.” | Not started group G5 | post-transfer.ts | |
| A caller's tour-day call ended without reaching anyone | “…the call ended without a hand-off, so someone should be ready to greet them…” | jargon | “{name} called on their tour day and didn't reach anyone. Please be ready to greet them at {time}.” | Not started group G5 | tour-day-fallback.ts | |
| Someone writes again while the team has their conversation | “…has written in again while this thread is with the team. Clara sent nothing back…” | jargon | “{name} wrote again while your team is handling their conversation. Clara hasn't replied, so they're waiting on you.” | Not started group G5 | gated-inbound-team-notice.ts | |
| A tour slot was lost | “The prospect has not been told.” | jargon | “They haven't been told yet. Please reach out to confirm the time or offer another.” | Not started group G12 | notify-team-of-lost-tour-slot.ts | |
| Staff answers a question Clara passed on | Text | “that's the answer I already have applied” | jargon | “Thanks, I already sent them that answer.” | Not started group G6 | reply-release.ts |
| Staff answers part of a question | Text | “…on their thread, so flagging that piece…” | jargon | “I still need an answer on {topic}.” | Not started group G6 | decision-request.ts |
| Staff says drop it | Text | “Done — dropped it” (sent even when the drop failed) | wrong promise | Sent only after it actually happened. | Not started group G6 | decision-request.ts: drop ack |
| Urgent question to staff | Text | “Flagged {urgency code}” | internal id or code | “This one's urgent.” | Not started group G6 | decision-request.ts: urgency phrase |
| Reminder of something the manager needs to act on | Text | “Clara's read of it:” | jargon | “Here's what I understood:” | Not started group G6 | pm-action-reminder-copy.ts |
| Renewal staff texts | Text | “PropFlow:” prefix, “unit unknown”, “start a non-renewal”, “the PMS” | jargon | No prefix; the resident's name instead of “unit unknown”; “end their lease”; “AppFolio” (the actual system). | Not started group G4 | renewal-notify.ts, renewal-escalation-copy.ts, pms/display.ts |
| Renewal emails that didn't send | Digest lines “email failed”, “Renewals is switched off for this company” | error text | “We couldn't reach these residents by email. The team is looking into it.” Internal settings are never mentioned. | Not started group G4 | renewal lapse digest | |
| A resident's unit needs confirming | Text | “PropFlow: …(ref X)… a property that isn't identified yet… Open your PropFlow dashboard” while replies take YES/NO | internal id or code | “{name} says they live at {unit}. Is that right? Reply yes or no.” | Not started group G7 | confirmation-review-notification.ts |
| Several unit confirmations are waiting | Text | “You have 3 pending unit-confirmation reviews (A1B2, …)”; the yes reply is acknowledged even when not applied | internal id or code | Ask one at a time. Acknowledge only after it's saved. | Not started group G7 | handle-confirmation-review-reply.ts |
| Bulk message waiting for approval | Text | “Reply with the code + your decision… Codes: …”; “Something went wrong on my end and your message has NOT gone out…” | error text | Ask about one message at a time by its topic. On failure: nothing to staff; engineering is paged. | Not started group G7 | handle-mass-comms-confirm-reply.ts |
| Turnover follow-up | Text | “Just checking in on unit…” with internal wording | jargon | “How's unit {n} coming along?” | Not started group G8 | capabilities/turnover.ts |
| Walk-through saved but not assessed | Text | “…the condition assessment could not be completed… re-run the assessment.” | error text | “Unit {n}: I saved everything from your walk. Nothing has been charged or scheduled yet.” Engineering is paged. | Not started group G8 | call-ended/route.ts (~3392, ~3408) |
| Work plan not confirmed | Text | “I wasn't able to confirm the work plan — let me try again.” (nothing retries); “job(s)” | wrong promise | “I haven't confirmed the plan yet. Reply “yes” to approve it, or confirm it on the Turnovers page.” | Not started group G8 | conversation-manager.ts (~13594) |
| Emergency, nobody answered | Text | “…an unspecified unit…”, “a possible emergency (details unclear)” | jargon | “Emergency at {property}: a resident reported “{issue}” and hung up before we reached anyone. We called this line and no one answered. Please call them back now at {phone}.” | Not started group G9 | emergency-no-answer-ladder.ts, emergency-relay-call.ts |
| After a tour | Text | “Any notes you'd like me to add to their card?” | jargon | “Anything I should add to their notes?” | Not started group G12 | tour-checkin-ask.ts |
| Self-guided tour needs a lockbox code | Text | Raw date like 2026-10-02T15:00:00Z; “the prospect” | internal id or code | “Thu Oct 2, 9am”; the person's name. | Not started group G12 | self-guided-lockbox-ask.ts |
| What triggers it | Channel | What it says today | Problem | Proposed wording | Status | Where in code |
|---|---|---|---|---|---|---|
| A work order is sent or updated | Text | Our internal record id instead of the job number | internal id or code | The job number from AppFolio; the job title when it has no number yet. | Open #14342 (title fallback still to add) | vendor texts (7 places) |
| Vendor reply we can't read | Text | The whole job sheet pasted back | error text | “Thanks, got it. The property team will follow up on this job.” | Open #14342 | handle-vendor-completion.ts: fallback |
| Vendor writes with no open job | Text | “…we don't have an active work order assigned to you right now. If you believe this is an error…” | jargon | “Hi {name}, I don't see an open job for you with us right now. If you think there should be one, please call the property manager.” | Not started group G1 | handle-vendor-completion.ts (5 places) |
| Vendor says they'll come back | Text | “Understood {name} — noted on the WO and letting the tenant know…” | jargon | “Thanks {name}, noted. I'll let the resident know about the return visit.” | Not started group G1 | handle-vendor-completion.ts (~1108) |
| Vendor sends times we can't read | Text | “I couldn't parse specific time windows from your message.” | jargon | “I didn't catch the times you're free. Could you send 2 or 3, like “Tue 9–11am”?” | Not started group G1 | handle-vendor-completion.ts (~1736) |
| Resident cancelled before the visit | Text | “…confirming stand-down on the {title} job. The tenant canceled it…” | jargon | “No need to go out for the {title} job. The resident cancelled it just before you headed out.” | Not started group G1 | handle-vendor-completion.ts (~1037) |
| Resident cancelled (in-house tech) | Text | “Tenant cancelled this WO - you can stand down.” | jargon | “The resident cancelled this job. No visit needed.” | Not started group G1 | tech-sms-dispatch.ts |
| Turnover job for an in-house tech | Text | “Turnover work ready - Unit {n}” | jargon | “Unit {n} is ready for move-out work.” | Not started group G1 | in-house-dispatch.ts |
| Tech texts the leasing-only line | Text | “…we're not able to take maintenance or repair requests on this line…” | wrong promise | “This job is being handled by the property office directly. Please reach out to them about it.” | Not started group G1 | fail-open-fallback-reply.ts |
| Vendor dispatch, quote and chase emails | “[D-1234]” tags and ALL-CAPS headings (not live today) | internal id or code | Plain subject with the job title; no tags. Fix before these go live. | Not started group G1 | vendor dispatch email templates |
Each is one concern, under 300 lines, wording and source fixes only. Say go on any number and a builder picks it up.
Vendor and in-house tech wording; job title fallback when there's no AppFolio job number.
Rating prompt and reply by score; repair line pointer; silent on a failed update.
Move-out wording, lease-end dates, skip sends with missing rent or date, greeting placeholder, email capture.
Drop the prefix, name the resident, say AppFolio, no internal settings.
Property line, hand-off text, caller role words, follow-up page subject, transcript and tour-day notes.
Acks only after the action happens; plain urgency and summary words.
One question at a time, no codes, no dashboard pointer, silent on failure.
Check-in, walk-saved note, work-plan line that doesn't promise a retry.
Carbon monoxide wording, no-answer text, no “unspecified” or “details unclear”.
Error greeting, take a message when a transfer fails, plain tool results, availability line, repair greeting.
Send nothing instead of the canned greeting or the correction; test-number check; HELP reply; address builder; parked ack.
“notes” not “card”, readable date, the person's name.