Leasing agent first. Clara gets stuck, texts one person, gets a plain answer back, and replies to the prospect herself.
Built and proven at the Willows on 2026-09-22. Not turned on for any customer. 2026-09-22. New page because the Camellia-era coworker hub is a release record of what shipped; this is the reviewable plan, and it grows into tonight's walkthrough with mocks.
Contents
Jason's worry is the reason this is not an email: "if Clara is just trying to ask for help on the leasing email, I'm afraid it's gonna get drowned." The shared inbox is a noisy catch-all. One named person on one phone is not.
Her whole product is her text thread. No login, no app, no buttons. Prospect names below are invented.
Mock A is Loop A. Mock B is Loop B. Both arrive from the property line Clara already uses, so Kat only ever has one Clara number.
The same conversation, with the human turn shown in line with Clara's. Nothing new is claimed here; it is the turns we already record, put on one thread.
This was the sketch. Tonight's section has the real page, built and screenshotted.
Each one has a default. Strike any you disagree with and we build the rest.
| Piece | State | Where it lives |
|---|---|---|
| The ask record and its state machine (open, waiting on staff, resolved), with the question and the answer kept verbatim | Exists | src/lib/data/dynamo/escalation-matter.ts, matter-state.ts |
| Recognising an inbound staff person by phone, including the leasing-agent role | Exists | src/lib/domain/staff/inbound-resolution.ts |
| Relaying the answer back to the prospect, picking email or text by the prospect's own address | Exists | reply-release.ts (relayAnswerToPerson) |
| Writing the answer into property knowledge so Clara never asks twice | Exists | src/lib/domain/escalation/teaching-capture.ts |
| The "handed off to the team" note on the guest card | Exists | open-matter.ts (writeEscalationHandoffNote) |
| Assigning a guest card to a named AppFolio user | Exists, but only a hand-run script produces it | guest-card-outbox.ts, scripts/guest-card-assign-to-user.ts |
| Test harnesses for the whole coworker and escalation path | Exists | scripts/coworker-harness/, scripts/escalation-crucible/ |
| Sending the ask as a text: today the ask has exactly one send site and it is email | Build | open-matter.ts, twilio/client.ts (internalRecipient) |
| Matching Kat's reply text back to the open ask | Build | mirror confirmation-review-reply.ts; getEscalationMattersByPhoneAndProperty already exists |
| Automatic assign-to-user, plus a per-company map of who that user is | Build | open-matter.ts calls the existing writer |
| The real reason in the handoff note instead of one fixed sentence | Build | open-matter.ts — the free-text slot is already there |
| A "tour happened" signal, and an author on the note, for Loop B | Build | tour-timers.ts, guest-card-turn-note.ts (work orders already carry an author) |
/review and it is the exact shape the 08-14 rule forbids. We name it so it stops being invisible; we do not extend it.Everything below is a real text message between four numbers we own, sent through Clara's own line at the Willows. Kat is a bench phone we bought, never anyone's personal cell. The prospects are bench phones too. Nothing touched a customer.
Four loops ran end to end: Clara stuck → asks → answers; the same question a second time, answered from memory; the after-tour ask; and the two things Kat can start herself. Message ids and the full run log are at the bottom.
Kat's number never reached the prospect. The answer came back in Clara's voice, on the prospect's own thread.
The moment Kat answered, the answer became the property's own knowledge, through the same path that already captures staff answers today:
A second prospect asked the same question a minute later. Clara answered from that entry and texted Kat nothing — checked against Twilio itself, not against the script's own counter.
Those notes were saved against the tour on our side. Writing them onto the AppFolio card was deliberately left out tonight, per the ruling below — the run logs exactly what it would have written.
This is the offshore-assistant job: the calendar and the follow-ups. Kat types like a person, and Clara works out the rest from the clock and Kat's own calendar.
Kat never named a tour when she said she was running late. Clara picked the next one on the calendar and said out loud which one she assumed, so a wrong guess is one word away from being corrected. The times she offered for the reschedule came from the same calendar we use to offer prospects tour times — open slots only, never invented. If that calendar cannot be read, she says so in one line instead of guessing.
The wall-clock time for this loop was set to the middle of a work day; the run itself happened at 10:07 PM. The tours, the calendar read and the open slots are real.
This is the app, not a drawing of it. Same conversation page the team already uses, running against the data this proof wrote. Every step of the hand-off is a row on the prospect's own thread, so "what happened after Clara got stuck" is readable by someone who was never on the text thread.
Screenshots taken headlessly against the app running locally on the proof branch, with each card's details opened. The rows are six new message types, added to the existing list — nothing else about the page changed.
Before this ships we ran the "should Clara ask Kat?" decision against every real prospect message we have — 4,875 turns from Western Slope (2,079), Situs Group (2,460) and Camellia (336). Each one was replayed inside the thread it actually arrived in, with the earlier messages from the prospect and from the real leasing team, and with the property and company knowledge that is on file in production today. A stratified sample of 1,657 turns was graded; every rate below is weighted back to the whole set. This was a measurement, not a fix: nothing was changed to make the numbers look better.
| Client | Turns graded | She asks now | She should ask |
|---|---|---|---|
| Western Slope | 856 | 15.4% | 12.4% |
| Situs Group | 468 | 13.6% | 16.8% |
| Camellia (JP&Co) | 333 | 2.4% | 4.5% |
| All | 1,657 | 13.6% | 14.0% |
Of the 299 asks she did make, 109 — more than a third — were on homes where there is no knowledge on file at all. An empty knowledge base is the single biggest driver of noise.
| # | Fix | Kind | Turns |
|---|---|---|---|
| 1 | She asks about a fact the company knowledge already answers — application, deposit, pets, co-signer, lease length | prompt | 62 (3.7%) |
| 2 | Nothing on file answers it and the prospect cannot move without it | knowledge gap | 35 (2.1%) |
| 3 | A red flag goes straight past her — eviction, criminal history, income short of the requirement, a voucher question | prompt | 19 (1.1%) |
| 4 | A one-off exception only a person can grant | prompt | 17 (1.0%) |
| 5 | Booking, rescheduling or confirming a tour is always hers — she asks a human anyway | prompt | 14 (0.8%) |
Names, numbers and exact dollar amounts are replaced. Asks that were noise:
| What the prospect said | She did | Should have |
|---|---|---|
| "Do you accept a voucher for that house? I wanna know that first." | Asked a human | Answered — company policy on file says a voucher counts the same as any other income |
| "Do you need one reference for each of us, or two references for each of us?" | Asked a human | Answered — the staff reply earlier in the same thread already says two total |
| A thumbs-up reaction to the prospect's own earlier message | Asked a human | Nothing to answer |
Asks she should have made and did not:
| What the prospect said | She did | Should have |
|---|---|---|
| "If a recent eviction an automatic no? That eviction from my wife was from 2024…" | Answered herself | Asked — only a person decides an exception to the no-evictions rule |
| "I am a stay-at-home wife and not working. My husband is self-employed…" | Answered herself | Asked — no income on one applicant, screenshots instead of the required proof |
| "The pet policy site says you only allow up to two…" (they have a third pet) | Answered herself | Asked — a third pet is the leasing team's call |
We replayed 150 escalations with a staff answer attached — 74 of them the real answer the real team gave in that thread. Sixteen were genuine policy questions worth remembering; the other 134 were about one person and correctly were not stored. Thirteen of the sixteen were answered, remembered, and stopped escalating on the re-run. So the learning flywheel catches roughly one escalation in ten, which is what you would want — but two holes showed up: nothing checks that what gets stored is actually an answer (one case filed a personal apology as property policy), and nothing marks an answer as seasonal (a "swamp coolers start later this week" reply was filed as standing policy).
Reading 4,539 messages across 1,034 real conversations at Western Slope and Situs: 94% of prospects got a human reply, median 19 minutes, 81% same day — but the person had to chase 378 times. A real question is almost never ignored; only 36 of the 269 unanswered threads contained one. Co-signers get a condition, never a no (26 out of 26). Pets and short leases are priced, not debated — "the month-to-month fee will be $150 on top of your recurring fees." Nobody negotiates rent. Voucher answers flip by property, which is exactly why they have to live in each home's knowledge. The only thing a human genuinely chewed on was eviction and credit: median 13.3 hours to reply, forty times slower than everything else — that is the shape of the small subset Clara should hand over.
Twelve knowledge entries were drafted out of those replies, and one conflict surfaced that the client has to settle: one thread says there is no application fee, another quotes $50 per applicant.
Western Slope and Situs inbound email is not captured anywhere — their turns above come from the AppFolio messaging panel, which only holds texts. Camellia's 291 email turns come from our own records. The grader was checked with a planted case: an obvious escalation labelled "she can answer this" came back as an ask, and an obvious tour-time question came back as an answer.
Run it again: npm run escalation:bar on branch harness/escalation-decision-bar. Full results, the confusion table and 60 examples are in the branch at evals/replay-harness/escalation-bar/results/.
On the 22nd Jason Fish asked a plain question: if someone emails the Western Slope leasing inbox saying they are interested in a home, does Clara find it, make the guest card, and answer? Fede said yes. Today that inbox only handles tour messages, so the rest of it is not on. We read every message in it from January 1 to September 22 — 10,887 — and found 59 people writing in about a home in their own words: about six a month, against roughly 150 leads a month relayed in from Zillow. Camellia looks the same from the other side — of its 95 email threads, 94 started as a listing‑site forward and one was a person writing in. Nothing was sent, moved or marked read.
We tested Clara on those real past emails — 57 of them still had a readable body — and graded every draft against the same bar we use for guest‑card replies. The point of this section is the order: which of these we can turn on now, and which needs a change first.
| Group | What it is | Emails |
|---|---|---|
| A | Asking to tour, and the home is named | 22 |
| B | A question about a named home, but not a tour | 16 |
| C | A general question — fees, applying, policy — with no home | 2 |
| D | Interested, but no home and no specific question | 15 |
| E | Everything else (a thank-you, a dead end) | 2 |
Groups C and D are really one problem seen twice: 17 of the 57 emails arrive with no home attached. Two of the 59 had nothing left to read and were not replayed.
| What they wrote | What Clara would have said | Grade |
|---|---|---|
| Re: 624 Eisenhauer St — "Hi Kat, 10:30 on 3/18 works for me. Thank you so much." | "You're all set — I'll see you at 624 Eisenhauer St on Tuesday, March 18th at 10:30 AM. A leasing agent will meet you at the home." | Send as‑is. Nothing wrong. |
| Re: Duplex in Orchard Mesa — "Are we able to do a Saturday? If not I will see if I can get off early one day this week." | "Saturday tours are available — I can get you set up for a weekend appointment between 10 am and 3 pm. What time on Saturday works best?" | Send as‑is — but only after the fix below. Before it she stalled: "I can check availability … could you share your name first?" |
| Re: Availability for end of February — "What address are we meeting at?" | "The tour is set for 1 PM tomorrow — the home is at 1133 N 18th Street, Grand Junction." | Would fail. That is the management company's office. The prospect drives to the wrong building. |
| What they wrote | What Clara would have said | Grade |
|---|---|---|
| "I have an appointment to see the house on Florida, Wednesday at 2:00. I was wondering what your credit score requirements and your income requirements are. Could I please have an application?" | Credit: no published minimum, the application looks at the whole picture. Income: about twice the monthly rent. | Needs an edit. Facts right, but it runs long and never actually sends the application. |
| Re: 1009 Colorado Ave Apt C — "I assume the pending application is likely to be approved?" | "This is a screening judgment, Rule 7.0 applies. I also don't have context about who this person is …" | Would fail. Her private thinking ended up in the email body. |
| "If you could send over the leasing forms for the 4 bed, 3 bath townhome that would be great." | A bulleted list of what to bring, the fee, and "you can apply by emailing the leasing inbox or calling the office." | Would fail. They asked for one thing and got a policy wall — and were told to email the mailbox they just emailed. |
| What they wrote | What Clara would have said | Grade |
|---|---|---|
| "Do you have any studio or one bedroom apartments available for about $1,000 a month that takes Section 8, available March 1?" | "Voucher acceptance is something our leasing team handles … I'll have them confirm. As for availability, I don't have a specific property …" | Would fail. The voucher answer is already written down — vouchers count like any other income — and she pushed it to the office anyway. |
| "I'm looking for a 4‑bedroom near the university for four of us, 2+ baths, ideally a basement." | "I don't have a specific home to point you to right now … I'll flag your search with the property team." | Would fail. Twice says what she doesn't have, then promises a follow‑up nobody owns. |
| "Can you send me the link to your portfolio?" | "You can browse all of our available homes at westernslopepm.com — or tell me an area, bedroom count or budget and I can narrow it down." | Send as‑is. Nothing wrong. |
The pattern across C and D is one thing said many ways: with no home, she has company policy and nothing else, so she either says what she is missing or pushes it to a person. Neither is what a leasing agent would do.
Group A is the class to turn on first, because it is the one the inbox already handles and the one that fails for a single, fixable reason. We tested exactly that: match the address in the subject line to the company's own property list, tell Clara what we found, and change nothing else. Same emails, same rules, same bar.
| Group A, 22 emails | Before | After |
|---|---|---|
| Good enough to send as‑is | 7 | 11 |
| Needs an edit | 7 | 3 |
| Would fail | 8 | 8 |
| Replies quoting the office as the home's address | 3 | 0 |
The wrong‑address failure is gone. The eight that still fail are not about the home: four are a tour time the test could not actually book, because this test runs her reasoning without a live calendar, and four name a home that is no longer on the company's property list at all, so there are simply no facts to give.
On the phone Clara does not guess which home someone means — she asks, pins it down, and then answers. Email should work the same way. As a separate change, after tours:
Direct emails use the same coworker loop as everything else on this page: when one asks something Clara cannot answer from what is written down — a missing policy, an exception, a red flag — she texts the leasing agent the same short ask, relays the answer back, and saves the fact so she never has to ask twice. There is no separate path for email. The practice rounds above should grade these emails too, so the sharpness of the ask is measured on this channel and not just on guest cards.
None of this is Western Slope‑specific. The home match reads whatever property list the company has on file, so Situs Group gets the identical behaviour the day their mailbox is connected.
The AppFolio side — making the guest card, assigning it to Clara, putting a note on it, logging that an email went out — is not new work. It is the same guest‑card writer the rest of Clara already uses; a direct email is just another way a prospect arrives. Creating a card is already one of its jobs, so nothing is missing there. The one thing it needs from us is the home, because AppFolio will not accept a card that is not attached to a property.
We prove it at the Willows, our test property, with the guest‑card test we already run there:
Worth fixing, not urgent — six emails a month. The reason to fix it is the shape of the failure, not the count: a prospect sent to the wrong address is worse than a prospect who waits for Bev.
Tonight. A local proof of the loop, no pull requests, quick iterations. Then this page grows into the walkthrough: real texts and real card screenshots pasted in.
After your feedback. Roughly six small changes, one concern each, all dark: the text ask leg; the reply-to-ask matcher; automatic card assignment; the per-company staff map; the real reason on the note; and the tour-happened signal with a note author. Proven at the Willows and at Fairhaven. Then a company setting you flip.
Two Fairhaven facts before tonight. Its line is voice-only, so it cannot receive a text yet. And it has no staff person on it at all, so one has to be created.
This is the fourth and final proof run before Kat's own switch-on. Real texts, real production, the Willows test property only (org_sandbox). Staff tester's own phone stood in for Kat; every prospect was a bench number we own. Nothing in this run touched Western Slope, Camellia, or Riley Chen's real card. Run window: 12:29–13:07 MT (booking scenarios) plus 11:30–11:45 MT (the post-tour check-in, same afternoon).
| Before (run 3 and earlier) | After (run 4, this proof) | Fix |
|---|---|---|
| A staff text could get tangled into a prospect's own tour — Clara would tell staff one thing while quietly acting on a different person's booking. | Zero mix-ups across all 5 write scenarios in this run. Every booking, reschedule and cancel landed on the exact person named in the text, checked directly in the database, not just from Clara's reply. | The fix that keeps staff texts out of the prospect tour pipeline (PRs 12455 and 12513) |
| A desk booking for a brand-new prospect never created an AppFolio guest card at all — the card-creation step was simply skipped. | The card-creation step now runs first, every time, for every new prospect. (Separately, AppFolio itself rejected those card-creation attempts this run — see "what's still open" below. That's a different, already-diagnosed problem, not this bug coming back.) | Desk booking now queues the AppFolio card before it books the showing (PR 12508) |
| Typing an unreal apartment number like "999" got silently accepted as a real unit. | "999" was rejected outright, with the real list of units offered instead, on the first try. | Unit-honesty fix from an earlier round in this same chain |
| The staff text thread could get stuck behind an unrelated, already-dead approval request and stop responding. | No wedge at all this run — every staff text got an immediate, on-topic reply. | Wedge fix (PR 12455) |
Every message below is a real text between the staff tester's phone and Clara's Willows number, in Mountain Time. The small text under each bubble is the Twilio message id, for anyone who wants to look it up directly.
A second, older check-in for a different Riley (Riley Chen, card 112 — never touched by this proof, banned from every run) was open in the same window and was correctly left alone. Clara attached the "loved the natural light" reply to the right Riley.
| Screenshot | What it proves |
|---|---|
| scen1-propflow-alex.png | Alex Rivera's page in PropFlow right after the 11am booking. |
| scen1-appfolio-132-showings.png | AppFolio's showings panel for Alex's real card (132) still reads "no showings scheduled" — the booking never synced across. This is NEW-BUG-3, below. |
| scen2-propflow-casey.png | Casey Bench's new PropFlow record after her card-creation-and-booking exchange. |
| scen2-appfolio-search-casey.png | Searching AppFolio for "Casey Bench" finds nothing — her guest card genuinely never got created there. |
| scen3-propflow-drew.png | Drew Bench's PropFlow record, booked under his own name, not Casey's or Alex's. |
| scen3-appfolio-search-drew.png | Same empty AppFolio search result as Casey's — his card didn't sync either. (This shot looks pixel-identical to Casey's; that's expected, it's AppFolio's generic "nothing found" screen.) |
| scen4-propflow-alex.png | Alex's PropFlow record after the reschedule, now showing 2:00 PM. |
| scen4-appfolio-132-showings.png | AppFolio card 132's showings panel, still empty after the reschedule — same unsynced booking as scenario 1. |
| scen5-propflow-casey.png | Casey's PropFlow record showing no note was ever attached — matches Clara's honest "didn't go through" reply. |
| scen6-propflow-drew.png | Drew's PropFlow record after cancellation. |
| scen7-propflow-alex.png | Alex's record at the continuity check — still 2:00 PM, unit 204. |
| scen8-propflow-riley.png | Riley Bench's new PropFlow record, booked same-day for 10:30 AM. |
| scen8-appfolio-search-riley.png | AppFolio search for "Riley Bench" finds nothing at the time of booking — her card hadn't been created yet either (it was created later, at the post-tour step; see scenario 9). |
| # | Scenario | Verdict | Proof, one line |
|---|---|---|---|
| 1 | Book on an existing card, with a unit (Alex Rivera) | PASS | Right person, right unit, right time, confirmed — checked directly in the database, not just Clara's reply. |
| 2 | New prospect by email only (Casey Bench) | PARTIAL | The booking itself is correct in PropFlow; the AppFolio guest card failed to create (systemic issue, not this scenario's fault). |
| 3 | "Which unit?" with a bad answer (Drew Bench) | PARTIAL | "999" was correctly rejected and the real unit booked correctly; same AppFolio card-creation failure as scenario 2. |
| 4 | Reschedule (Alex Rivera to 2pm) | PASS | Tour moved to 2:00 PM, unit unchanged, other prospects' tours untouched. |
| 5 | Add a note (Casey Bench) | FAIL | Blocked entirely because no AppFolio card exists yet — but Clara told the truth about it instead of claiming the note was saved. |
| 6 | Cancel (Drew Bench) | PASS | Drew's tour cancelled; Alex's and Casey's tours confirmed unchanged. |
| 7 | Continuity check ("is Alex's showing still on?") | PASS | Answer matched the real database state exactly, after the reschedule. |
| 8 | Near-term booking, same day (Riley Bench) | PASS | Booked correctly for that afternoon; same AppFolio card-creation failure as 2 and 3. |
| 9 | Post-tour check-in (Riley Bench) | PASS | Right Riley, note saved in PropFlow, application email sent automatically — the AppFolio copies of the showing and the note are still stuck (see below). |
Also checked and confirmed clean this run: no invented "that slot just got taken" excuses, no wrong unit ever named for a real showing, no leftover turnover disclaimers, and the wrong-person mix-up from earlier runs did not come back once.
Marked Proposed — pending review.
Recommendation: A. Every failure this run was on the AppFolio side, and Clara was honest about every one of them instead of claiming a write that didn't happen — nothing in this run put a wrong answer in front of a person. Fede's own test week (starting 9/28) is the last check before Kat's Wednesday go-live either way.
Recommendation: A. Keeps one calendar per property regardless of who booked the tour, so nothing has to be reconciled between two calendars later.
Recommendation: B. This run confirmed the code already does this (no SMS consent was recorded off a staff text for any new prospect) — keeping it this way means Clara never sends a first text to someone who never agreed to receive one from us.