Who decides the terms, who talks to the tenant, who sends the paperwork, and how a customer steps from "we review everything" to "Clara runs it".
2026-10-12 · Proposed, pending Fede's review · sources and pending inputs in §12 · internal
1. This week 2. The levels 3. How it fits 4. Roadmap, minimum slices 5. Today, and the tangle 6. What the tenant and office hear 7. Notice to vacate 8. Settings 9. Camellia and the market 10. Testing 11. Decisions Fairhaven proof Month cards prototype 12. Reference
Four layers, and today three of them hang off one switch. Who decides the terms. Who talks to the tenant: always Clara. Who sends the paperwork. And the rollout gate, Off → Supervised → Live, whose only job should be whether a real tenant sees Clara's words before we have watched her for a week.
flowchart LR
P["Lease 90 days out"] --> D{"1 · who decides\nthe terms?"}
D -- "Clara, by policy" --> C
D -- "the team reviews\nthe monthly list" --> C
C["2 · Clara talks\noffer · reminders · replies"] --> A{"tenant says"}
A -- yes --> W{"3 · who sends\nthe paperwork?"}
W -- Clara --> AF["AppFolio offer,\nsigned in the portal"]
W -- office --> OF["'send the paperwork'\nemail to the office"]
A -- no --> N["notice-to-vacate\nguidance, nudges"]
A -- counter --> E["escalation\nto the office"]
G["4 · rollout gate: Off · Supervised · Live\nholds Clara's words for a week, nothing else"] -.-> C
style G fill:#fff3cd,stroke:#b45309,color:#333
| When | What | Whose press |
|---|---|---|
| Wed 10/14, client meeting | Western Slope to Supervised: their team reviews the list, the office sends paperwork, we approve every message | four settings: Fede |
| Week 1 | Every message approved by us; 24 to 48 hour battle test on Fairhaven | us |
| Week 2 | Live: their team approves the list, Clara sends, nobody from PropFlow in the loop | Fede |
| Later, per customer | Clara sends the paperwork → the list becomes optional → meeting notes feed the decisions | Fede, per customer |
Six decisions in §11.
This replaces the step order on the Western Slope page from 10/8: paperwork is no longer tied to Live (Fede, 10/12). The deliverable for Wednesday's meeting is the most basic version, live. Their team gets the monthly list and answers by email reply or on the page. Clara sends the offers and handles the replies. The office sends the paperwork. For the first week Fede and Gera approve every message before a tenant sees it. Week 2 goes Live with nobody from PropFlow in the loop.
| Setting | Today | For the flip | Why it matters |
|---|---|---|---|
| Renewals module | Off | Supervised | the flip opens the first list that minute (Lincoln and Courtyard leases are on it; 18 leases, 12 would send, 6 held, per the 10/12 dry run) |
| Who sends the paperwork | not set | the office | the 10/8 write set the rent rule, eligibility and the 90-day start but deliberately left this unset (ledger). Unset means Clara in code today: the robot would create AppFolio offers on day 0, before the list is approved, and AppFolio emails the tenant (per code comments). Fede 10/12: unset must mean the office, the lower level; fix below |
| Renewal reviewers | none | Kat, Jay | with no reviewers the monthly list goes to nobody |
| Rent rule | flat since 10/12 evening (was market rate) · 12-month only · month-to-month +$150 | done | their team changes any rent on the list anyway |
| Renewal call | off | off | as agreed on the 10/7 call |
| Per-building "autonomous renewal" flag | 0 of 90 buildings | delete it (fix); until then, on for every building on the list | a Camellia-era leftover Fede never asked for (10/12); the daily check skips any building with it off, so the org-level mode alone starts nothing. Buildings that never get renewals (affordable housing) are a different thing: the per-building module Off row, already used for Lincoln and Courtyard |
| Company go-live stamp | live | live | emails can go; the two global arms are on |
Items 2, 3 and 5 are fixes to live behavior and proceed under the standing grant. Item 1 is off the table (D1 = b). Item 4 waits for D3. Three more fixes from Fede's 10/12 rulings, no switch: (7) an unset paperwork sender means the office, never Clara ("it wouldn't make sense to default to a higher autonomous level and accidentally send it out"); Camellia's and Willows' rows were pinned to Clara on 10/12 22:40Z so nothing changes there (ledgered); the code default flips in PR #19100 (merged 10/13 00:30Z; the AppFolio robot then runs only on an explicit "Clara"); (8) the per-building autonomous flag is deleted (PR #19080, merged 10/12 23:20Z; Willows' renewals row set Off the same night so the test property does not start 85 held renewals; leftover writes to the dead field: issue #19083, stale runbook wording: #19088); (9) the renewal reviewers move into the customer's own settings page, not a staff-only screen (not started; UI gets a preview before merge). "Offer" on this page means Clara's first text with the terms, never the paperwork.
flowchart LR L["Monthly list\nKat / Jay: approve, change, skip\nby email reply or on the page"] --> C["Check before send\n(Supervised week only)\nFede + Gera, one page"] C --> O["Offer text + email\nto the tenant"] --> T["Tenant replies"] T --> H["Held reply\nSlack card + holds page\nnever expires silently"] --> S["Sent"] T --> X["Tool actions run at once:\nyes / no recorded; office emails\nwait for Live (the 10/10 rule)"] style C fill:#fff3cd,stroke:#b45309,color:#333 style H fill:#fff3cd,stroke:#b45309,color:#333
Week-1 approval surface for us: the Slack card in #alerts (the mention is hard-coded to Fede) plus the staff holds page under /admin. Gera's per-message reviewer emails stay off for renewals, one list a month (Fede, 10/9). The proposed fix is two roles on one reviewer list, "decides the terms" and "approves messages", never two lists.
A level is a preset of three settings, in our words and our onboarding, not a fourth switch (D5). The rollout gate wraps any level for its first week. A new customer starts at level 1 unless they ask for more; Camellia is level 3 today.
| Level | Who decides the terms | Clara | Paperwork | What the office gets (at Live) |
|---|---|---|---|---|
| 0 · Off | nobody | records what arrives, says nothing | office | nothing |
| 1 · Team decides, Clara talks Western Slope, week 1 | their team reviews the monthly list: approve, change, skip | offer, reminders, replies, questions, escalations | office | the list on the 1st · "send the paperwork" on a yes · escalation on a counter · "no formal notice yet" on a no · "needs you" at 14 days |
| 2 · Clara also sends the paperwork | their team reviews the list | same | Clara in AppFolio, after the list is approved | the list · escalations · a weekly digest |
| 3 · Clara decides by policy Camellia today | the renewal policy | same | Clara | a monthly heads-up, no approval · escalations · "needs you" |
| 4 · With the team's context later | policy plus the team's internal notes, sent to Clara or from a meeting she joins | same | Clara | same as 3 |
Three settings the customer can see, one gate we run.
| Setting | Values | New customer | Who changes it |
|---|---|---|---|
| Who decides the terms new | their team reviews the monthly list · Clara, by policy | team reviews | customer, on the company page; per-building override |
| Who sends the paperwork exists | the office · Clara in AppFolio | office | customer |
| What Clara knows later | policy only · policy plus internal notes | policy only | customer |
| Rollout gate exists | Off · Supervised · Live | Supervised at turn-on | PropFlow; about a week, then Live |
Everything else is a rule, not a setting: the reminder cadence, which notifications go out at each level, how long a hold waits, the safety guards, the arms. §8 lists what to delete.
flowchart LR
subgraph today["Today: one stored value, 'drafts'"]
S1["Supervised"] --> H1["holds every message\n24 h, then dropped"]
S1 --> L1["opens the monthly list\n(exists only here)"]
end
subgraph target["Target"]
D2["Who decides the terms\n(customer setting)"] --> L2["monthly list,\nat any level that wants it"]
S2["Rollout gate\n(ours, one week)"] --> H2["holds every message,\nnever drops one"]
end
| Step | When | Minimum slice | Done when |
|---|---|---|---|
| Supervised, level 1 | by Wed 10/14 | the six items in §1 plus Fede's four presses | their team approved a list; we approved every message; no silent outcome for a week |
| Live, level 1 | week 2, from about 10/21 | flip to Live; nothing to build | a full cycle: list → offers → replies → yes, no, counter each handled with the office told |
| Level 2 · Clara sends the paperwork | when Jay's AppFolio templates are set per building | the AppFolio offer is created after the list is approved, not on day 0; list edits reach the offer and the letter | one renewal signed end to end at Western Slope |
| Level 3 · the list becomes optional | when the customer asks | "who decides" set to Clara; the list turns into a heads-up | a month with no list edits they would have made |
| Level 4 · internal notes | after the company-brain decisions | notes read when the offer is built; shown on the lease, never in the letter | one month where the notes changed an offer correctly |
Meeting the customer where it is: onboarding asks three questions in their words. Do you want to look at each renewal before it goes out. Does your office send the paperwork, or should Clara. Does Clara talk to your tenants. A customer may stay at any level for good; stepping up is one setting change plus one supervised week.
Checked in code on 10/12 by an independent inspection; the full matrix is in §12. Three findings matter this week: one stored value drives both the message holds and the monthly list; Supervised holds Clara's words but not her actions; and several paths end in silence.
| Step | Off | Supervised | Live |
|---|---|---|---|
| Daily check opens a renewal 90 days out | skipped, nobody told | opens; the monthly list opens on the 1st and right after the flip | opens; shows on the board |
| AppFolio offer (Clara paperwork) | never | day 0, before the list is approved; AppFolio emails the tenant (per code comments, unverified); a "no" never withdraws it | day 0 |
| Offer text, email, letter | refused, stamped, nobody paged | parked until the list is decided; released at once on approve; a 24-hour hold if the lease is on no list | sent on day 0 |
| List approved with edits | no list | Clara's words and our lease record change; the AppFolio offer and the letter PDF keep the old numbers | no list |
| Reminders, 60/30/15-day nudges | refused | held; released with the list; on a 24-hour expiry reminders stop and the board says "needs you" | on schedule |
| Clara's reply to the tenant | not sent; #alerts gets a post | held 24 hours, Slack card, staff page; then closed, the tenant hears nothing | sent |
| Tool actions behind a held reply | refused | run at once: yes and no recorded, escalation email sent, term change written to AppFolio | same |
| Office pages (no answer, 14-day signature, counter) | none | all muted; the escalation email still goes, but only to the building inbox | sent |
Fede proposed it on 9/28 ("a mode where we're reviewing, human in the loop… for a week or a few days… then you turn it fully on"); Gera designed and built it the same week. Fede's understanding holds on intent: core modules, outbound only, about a week, then Live. Three drifts: it holds every recipient, not just tenants and prospects; nothing in code times it or ends it; and for renewals it carries a workflow, the list, not just a soak. One catch for safety: actions still happen under it. The AppFolio offer is created on day 0 and, per code comments, emailed by AppFolio.
Level 1, office sends the paperwork. "Today" is Live unless marked; Supervised adds a hold in front of every Clara line.
| Tenant | Clara today | Office today | Target at level 1 |
|---|---|---|---|
| Yes | "You're all set… our office will send over the paperwork" | nothing; a "needs you" at 14 days if nothing is signed (muted under Supervised) | same words; at Live the office gets one "send the paperwork" email at once (D3); in the Supervised week it is held with everything else; 14-day nudge stays |
| No / moving out | silence (§7); intent to vacate is recorded | nothing; a fallback page that Supervised mutes | warm acknowledgment plus the portal notice-to-vacate link; nudges at day 3 and 7; at Live the office is emailed only if no formal notice by day 7 (D3) |
| Counter-offer | "I'll pass that along"; never negotiates | escalation email to the building inbox only; tracked case only if the building names an owner | same words; email falls back to the company inbox; case opens at the company owner |
| Question | answers from the offer block; off-offer terms escalate | a timeline line | same |
| Silent | reminders day 2 and 9, nudges at 60/30/15 days | "needs you" when reminders run out (muted under Supervised) | same; "needs you" shows on the board; the email waits for Live |
| Notice to vacate in the portal | nothing more to say; the workflow ends as declined | nothing from renewals; AppFolio's own automations start | same; the renewal closes and the list shows "gave notice" |
| Notice to vacate by email to the leasing inbox | unknown; not covered by any test | unknown | recorded as intent, replied with the portal link, office told; a battle-test row |
| STOP, then START | STOP blocks every text; START reopens only this company; no confirmation (open issue) | nothing; an approved send then fails silently (open issue) | confirmation on START; a failed approved send pages #alerts and shows on the list |
| Outcome | Who hears | Fix |
|---|---|---|
| Approved text fails at the carrier (opt-out, no line) | nobody; recorded as "failed" | page #alerts, show on the list (open issue) |
| Held reply expires after 24 hours | Slack says "the team has the thread"; the tenant hears nothing | D4: re-ping, never drop |
| Decline reply comes out empty | nobody; on a sandbox not even #alerts | two PRs tonight (§7) |
| No reviewers on the company | the list goes to nobody; Slack and the page only | refuse the flip without a reviewer |
| Per-building flag or an arm off | nobody; the workflow records "sent" | delete the flag and the arms (§8) |
| AppFolio emails before the list is approved (Clara paperwork; per code comments) | the tenant, from AppFolio, with the unreviewed offer | level 2 slice: create the offer after the list |
| Yes, office owns paperwork | nobody is told to send it | D3 |
| Escalation at a company with only a company inbox | nobody | fall back to the company inbox and owner |
| Office pages under Supervised | nobody (all muted) | "needs you" stays as a board state; the per-tenant email waits for Live |
The full notifications catalogue, 26 send sites and 29 silent outcomes, is §12-I.
Expected (Fede, 10/12): "Thanks for letting us know, sorry to hear you're leaving. The next step is a formal notice to vacate in your resident portal," with the link. The portal notice is the goal because it triggers the move-out automations in AppFolio. Some tenants send it by email to the leasing inbox instead; that happened at Camellia.
What happened on 10/12: the tenant texted that they changed their mind and were moving out. Clara recorded the intent to vacate and sent nothing. Not held, nothing to approve.
Why: the decline prompt already orders exactly the reply Fede expects, one warm sentence plus the notice-to-vacate instruction, but it tells Clara to write it before calling the tool, and the delivery engine sends only what she writes after a tool returns. Her post-tool output was blank, so the pre-tool text was dropped, and the salvage step restores only links and dollar amounts. No alert fired. The accept path works because she writes after the tool. The Langfuse trace of the turn was lost too: an empty reply returns before the trace is flushed.
Fixes merged tonight, no switch (issue and two PRs in §12-H): the engine never goes silent after a tool call (a marker-only final counts as blank → send the last real draft, else the no-reply alert fires; tests fail on the old code 8 of 15, pass on the fix), and the decline prompt mirrors accept (tool first, then the reply; the subscription eval went 0 of 6 → 6 of 6). The two decline eval rows had been grading the draft the tenant never got, which is why they stayed green. Proof: unit tests with a planted defect, the renewals text eval on the subscription runner, then a live Fairhaven decline in the battle test.
Rules for the design: the notice-to-vacate link is independent of who sends the paperwork (the team path blanks the signing link; the notice link must survive). A "no" is followed by nudges toward the formal notice at day 3 and day 7. The office hears about a "no" only when the formal notice has not arrived (D3). A notice that arrives by email is recorded, answered with the portal link, and the office is told: a battle-test row, since nothing covers it today.
| Customer settings | Today | Target |
|---|---|---|
| Rent rule, terms, month-to-month premium, eligibility, auto-start days | company row plus building override; locked to staff after go-live, yet the building override stays open to the customer | keep; one lock rule |
| Who decides the terms | does not exist; rides on Supervised | new company setting, per-building override |
| Who sends the paperwork | exists; unset means Clara; building override has no writer | keep; unset means the office (Fede 10/12: never default to the higher autonomy level); Camellia pinned to Clara explicitly before the default flips |
| Reviewers (list and messages) | staff-only screen; one list | on the customer's settings page (Fede 10/12); two roles on one list |
| Renewal call | on by default at runtime; the staff card shows "not set" as off | one default at every door; off for a new customer |
| Ours (rollout) | Today | Target |
|---|---|---|
| Module on/off, Supervised marker, per-building row | nothing stored means Live | store Off at creation; "Turn on" starts Supervised; show days in Supervised on the customer page |
| Company go-live stamp | holds email only | keep |
| Not settings: delete or fold | Why |
|---|---|
| Per-building "autonomous renewal" flag, the two global arms and their env fallbacks, the auto-start arm | four gates for one answer the module mode already gives; off means "recorded as sent"; Fede 10/12: never asked for the building flag. Production today: Fairhaven 9 of 11 on, Camellia 1 of 2, Willows 0 of 3, Situs and Western Slope 0; every company stores the module explicitly, so deleting the flag changes no company's state |
| Holdover flag plus its arm and env | three switches for one policy answer; belongs next to the month-to-month premium |
| Arm allowlists, rollback lists, excluded-person lists; the lapse digest flag; the module-default constant | fix-shaped; the lapse digest names its own removal trigger |
| Reminder cadence, hold expiry, notification matrix, safety guards | rules, not choices; the cadence doc disagrees with the code (48h/5d vs 24h/7d) |
Camellia, every real renewal since launch, read on 10/12 (full report in §12-K; tenants by initials). Engagement is low, as Fede expected, and silence is not a no: 12 of the 34 tenants who never replied renewed anyway, 9 by signing the offer Clara sent. Where Clara loses is after a reply: a "yes" followed by 14 days of silence, a promised signing link that never came, a counter-offer never answered. Six tenants kept getting renewal texts after they had signed, said they signed on paper, or gave notice; one wrote "Please do not text me again". Seven things never reached the office, among them a tenant who needs Spanish and Clara saying she was "looping in" the manager when nobody was. Five households show signs of speaking Spanish and every text and call to them was in English; none renewed. The 34 calls since June produced no decisions. Since the 9/28 doc: three more signed, the AppFolio sync closed 8 stale records by itself, no new round has started since 9/18, and leases ending 11/30 and 12/31 have gone 49 to 79 days with no message.
Ranked improvements, all bugs with no switch: stop the texts once a tenant answers; keep every promise made in the thread; make every hand-off reach the office. Then: Spanish offers, drop the morning call, chase a "yes" during the 14-day signature wait.
The market (scan of 16 vendors, 10/12; full table in §12). Nobody documents a staged autonomy ladder, a supervised mode per customer, or a dark launch for renewals; that is a gap in their public material, not proof we lead. The bundled threats are AppFolio Realm-X and Yardi Virtuoso, inside the PMS the customer already uses. Worth taking: a named human backup with full context at handoff (EliseAI), hard guardrails on offer terms with an audit trail (Frontdesk), a renewal-likelihood view per resident (EliseAI), approval workflows where the manager keeps the decisions (Rentify). The words the market uses for the human in the loop: "human backup", "approval workflows", "guardrails", "transparency and control for human operators". Nobody says "supervised".
The battle test runs on Fairhaven (the Western Slope shape) against registered team numbers only, then the Camellia regression replay stays byte-identical. Each cell gets a text, a log line or a screenshot; a cell with no evidence is red.
| Tenant does | Level 1, Supervised | Level 1, Live | Level 3, Live (Camellia regression) |
|---|---|---|---|
| Yes | held → approved → sent; office email | sent; office email | unchanged |
| No, moving out | held → sent with the notice link; nudges; office at day 7 | same, no hold | unchanged |
| Counter-offer | held; escalation email; case | same | unchanged |
| Question, then yes three turns later | held each turn | sent | unchanged |
| Silent for the whole cycle | reminders held and released; "needs you" | reminders; "needs you" | unchanged |
| Notice to vacate in the portal, then texts | renewal closed; no offer sent | same | unchanged |
| Notice to vacate by email to the leasing inbox | recorded, replied, office told | same | same |
| STOP, then START | START confirmed; approved send after STOP pages #alerts | same | same |
| Someone else answers the number | name captured, no offer details leaked | same | unchanged |
Office side, each with evidence: one list email to every reviewer with the hello@ copy; approve by reply; approve on the page with a rent edit and a skip; reject the list; a lease added after the list; a held reply re-pinged past 24 hours; a failed approved send; the yes email; the escalation email at a company with only a company inbox.
TL;DR: hold everything in week 1 and make "who decides the terms" its own setting now; the rest are shapes of notifications and defaults. Recommendation first on each.
Fede's own presses before the flip, not decisions: paperwork sender to the office; Kat and Jay as reviewers; the rent rule; the flip to Supervised. The per-building flags are ours to delete or, for Wednesday, Fede's to press on the Arms tab.
Every case below was run on the real production path on the Fairhaven test company (bench phone, test reviewer mailboxes). Unit tests are not counted.
Deployed: Lambdas 60c545df2, renewal worker bf71d79ae, web e45e27cf9. All carry the list email #19601, send-it-for-everyone #19649, counter note #19612, yes note #19647, plain frames #19700/#19701, and tonight's fixes #19824/#19827.
| Case | Result | Evidence |
|---|---|---|
| Monthly list email to reviewers | PASS | SendGrid delivered to both test reviewers; screenshot below |
| Reviewer opens the link, approves on the page, offer text goes out | PASS | hold approved 21:59Z, offer text delivered 21:59Z |
| Reviewer replies "looks good, send it" by email | PASS | hold approved 22:15Z, offer text delivered |
| Reviewer replies "don't send X's renewal at <building> 101, everyone else 12 months" | FAIL → fixed (#19827) → PASS 01:41Z | Clara: "approved… 101: not renewing. Everything else goes out as listed." |
| Reviewer replies "hold X, bump the others" | PASS | Clara asks a fair clarifying question (rent flat or pause?), no "did you mean" |
| Tenant texts yes → office note sent, not held | PASS | note delivered 22:08Z, Clara's tenant reply held |
| Tenant counters → office note sent, Clara's reply to tenant held | PASS | note delivered 22:03Z, reply held |
| Tenant who owes money is on the list and gets the offer after "send it" | PASS | "Owes $450 on their account" in the email; offer delivered |
| Review page shows the owes-money row correctly | FAIL → fixed (#19824) → PASS 01:44Z | rent box, Yes switch, "Going out", owes line; header matches the email |
| Renewals off at one building → nothing for that building | PASS | 7 leases before, 6 after |



Follow-ups filed, not blocking: #19820 (Clara forgets her own clarifying question), #19821 ("everyone else" cannot be applied by email), #19847 (approval joining a still-running offer job sends nothing, silently), #19848 (Status column clipped at 1280).
Western Slope: flip on Fede's word. Their list goes to their two reviewers; office notes for all 90 buildings fall through to the company leasing inbox.
Production: web 814b3788e9, Lambdas a5908e9a16, renewal worker cba57a5193. Every case on a freshly reset October list; all 20 emails to the two test reviewer addresses; zero tenant texts.
| Case | Reviewer wrote | Expected | Observed | Evidence | Result |
|---|---|---|---|---|---|
| A1 | "Hold off on her renewal, send the rest" | Clara asks who "her" is; question stored on the hold | "Which renewal should I hold off on? Your reply says "her" but doesn't name anyone. Nothing has been changed yet." Stored on that reviewer's notice, about units 13, 101, 305 and 4 (every woman on the list). Other reviewer: none. No lease decided. | hold eschold_rb_9dd95696b563b046069f7746 (cycle A, created 05:27:15Z); list email rk_5d4ef0022802365c556f0add; Clara 05:28:10Z Message-ID ce4dc843-e81b-4a57-96e3-1ceb718ac8c0@propflowai.co; pendingQuestion askedAt 05:28:10.213Z; RP2-A1-clara.eml, RP2-A1-state.json | PASS |
| A2 | "Bump the others to 12 months" (on Clara's question) | Clara asks again, naming her open question; no lease changes | "I still need your answer to my question first: Which renewal should I hold off on? … Nothing applies to the others (12 months) until I know. Nothing has been changed yet." 0 decisions recorded; the question stays about 13/101/305/4. | Clara 05:28:46Z e6765310-fce0-498c-b525-2ffafa682692@propflowai.co; askedAt 05:28:46.226Z; RP2-A2-clara.eml, RP2-A2-state.json | PASS |
| A3 | "I meant <resident>, keep her flat, the others at 12 months" | Named resident (unit 101) flat, every other resident 12 months, list still waiting, nothing sent | Clara asked AGAIN, with the text doubled: "I still need your answer to my question first: I still need your answer to my question first: … Nothing applies to the others (12 months) until I know. Nothing applies to the others (12 months) until I know. …". 0 decisions recorded, not even the flat rent. The question is now about 13, 305 and 4. | Clara 05:29:24Z b66a7be6-9338-42b6-b539-7ae89e255d74@propflowai.co; askedAt 05:29:24.088Z; RP2-A3-clara.eml, RP2-A3-state.json; raw model output in RP2-replays.txt (correct: keep_flat on the named resident + "the others" set_term 12); offline repro RP2-repro-a3.txt | FAIL (defects 1 and 2) |
| B | "Bump the others to 12 months, <resident> stays as proposed" (fresh list) | Brief: named resident unchanged, the others 12 months | Clara asked "Should <resident> at <building> 305 also get 12 months? Nothing applies to the rest until I know. Nothing has been changed yet." 0 decisions. The model writes no instruction for "stays as proposed" (3/3 replays), so the code asks. | list rk_1dc63dba2e1347f5374b21bb; Clara 05:30:52Z 9240f2d6-3ec3-4dd6-b250-c975588b45b8@propflowai.co; question about unit 305 only; RP2-B-*.eml/json, RP2-replays.txt | DIFFERS FROM BRIEF, matches the merged design. Safe: nothing applied, nothing sent. |
| C1 | "Everyone at 12 months except unit 305" (the email shows "Unit 305") | Clara asks about that one resident only (merged test: "Should X also get 12 months?") | "Should <resident> at <building> 305 also get 12 months? Nothing applies to the rest until I know. Nothing has been changed yet." Only 305 asked about (unit 101 is in the same building and was not). 0 decisions. | list rk_e9496ea02e00dd3b21383ca7; Clara 05:32:19Z fc83b8a3-3a86-4d5e-bba7-8c19de24083f@propflowai.co; RP2-C1-*.eml/json | PASS (asks, never applies) |
| C2 | "Everyone at 12 months except number 305" (fresh list) | Same | Same question, word for word, about unit 305 only. 0 decisions. | list rk_cbb5136ba743bd0086035c40; Clara 05:33:45Z 682d2951-849f-4af0-a01f-b29ce3c354d7@propflowai.co; RP2-C2-*.eml/json | PASS |
| D | "Don't raise the others, send" (fresh list) | "Should the rest of the list get <change>?", nothing sent | "Should the rest of the list get a flat rent? Nothing has been changed yet." List still pending, 0 decisions, no send. Stored question names no one (leaseIds []). | list rk_c634a2da58e9f151fdf1d376; Clara 05:35:11Z 71a657a4-711a-4844-b0c8-b61d88fd05f7@propflowai.co; RP2-D-*.eml/json | PASS |
| E | "Everyone at 12 months, send" (fresh list) | Approve, 12 months for all, no question | "Thanks, approved. What I changed: [7 rows]: 12-month term. Everything else goes out as listed." Hold approved 05:36:30.835Z by the reviewer. 6 rows approved with termMonths 12. The Fede-phone row stayed struck (renew false). Scan 05:36:51Z: TEAM-APPROVED for the balance-held test tenant, new saga saga_d2ed7a6f-898d-42f7-a4ee-8c3936c93f80, per-lease workflow run 01a13e10-32d8-7f36-9aa6-add39760034d. 05:36:53Z "deferring outreach to next send window, source: quiet_period" (23:36 local). No text yet; it goes to the bench in the morning send window. | list rk_9e83ee36afdfdc06e651d8b5; Clara 05:36:32Z ae6c7026-cb42-4219-9394-8fe3aa853529@propflowai.co; RP2-E-*.eml/json; renewal worker log /aws/ecs/propflow-renewal-worker-prod 05:36:51–53Z | PASS. The offer text is correctly held for quiet hours, so that part is not proven tonight. |
Defect found by A3: when Clara's question lists several possible residents, naming one of them does not count as an answer and each re-ask nests the previous one. Fixed in #19943 (no switch) and re-proven live below. Leftover: the "Recorded" email still lists the struck row as "12-month term", filed as #19942. Case B: 'stays as proposed' makes Clara ask rather than apply; matches the merged design, kept.
Production: merge b2d48c2a6 on web, Lambdas and the renewal worker. Same reset, same test reviewer addresses, zero tenant texts.
| Case | Reviewer wrote | Expected | Observed | Evidence | Result |
|---|---|---|---|---|---|
| A1 | "Hold off on her renewal, send the rest" | Clara's "which one?" question | "Which renewal should I hold off on? Your reply says "her" but doesn't name anyone. Nothing has been changed yet." Saved about units 13, 101, 305 and 4. No decisions. | list rk_50ca93e8e5de69e3b9906684; Clara 07:50:40Z be969620-0ac5-4073-91da-4bdc009889a3@propflowai.co | PASS |
| A2 | "Bump the others to 12 months" | One re-ask, original question once, not nested | "I still need your answer to my question first: Which renewal should I hold off on? Your reply says "her" but doesn't name anyone. Nothing applies to the others (12 months) until I know. Nothing has been changed yet." One lead-in, question once. No decisions. | Clara 07:51:03Z e1af0e47-5a2a-49fa-aaf7-7088d11979aa@propflowai.co | PASS |
| A3 | "I meant <resident>, keep her flat, the others at 12 months" | That resident flat (recorded), every other resident 12 months, question closed, nothing sent | "Recorded: <resident> at <building> 101: rent stays $2,395. [6 others]: 12-month term. The list is still waiting for your approval…" Unit 101: renew true, rent 2395. Units 13, 1460-4, 305, 4, 1254: termMonths 12, still pending. The struck test row stays struck. Question cleared. List pending, no send. | Clara 07:51:38Z 19ba1e51-a180-4871-a66d-566a569fa668@propflowai.co; decisions at 07:51:38.7–.8Z | PASS (the struck test row is still listed as "12-month term": known minor, #19942) |
| A4 | Fresh list. A1 again, then "I meant <resident>" | Her renewal held off (the original instruction); no change for the rest | A1: same "which one?" question (Clara 07:52:46Z 92d9ec24-0f6c-46b1-942f-05fd1c4daf0d). Reply 2: "Recorded: <resident> at <building> 101: not renewing. The list is still waiting for your approval…" Unit 101 struck (renew false). Every other row pending with no decision. Question cleared. No send. | list rk_afacf011a58a6a7ae46d6ccb; Clara 07:53:18Z 3f61de7c-1ec3-4683-a334-cdb5f725ee72@propflowai.co | PASS |
Run on production Fairhaven after the fixes deployed; every reply came from the bench number and every email went to a test address.
| Check | Result | Evidence |
|---|---|---|
| Defect 2 re-proven live after deploy | PASS | report-reproof2.md, Re-proof 4 check 1 |
| Defect 3 and defect 8 re-proven live after deploy | PASS | report-reproof2.md, Re-proof 4 check 2 |
| 3a. Offer text goes out at 8 AM Mountain, not during quiet hours | PASS | text SMe48ba4ea425fead17a35798f2829ce4d at 14:00:13Z |
| 3b. Counter by text → office note "countered their renewal" quotes the counter and our offer, agrees to nothing | PASS | RP4-counter-note.png; note id c2c97571-cb4e-45a9-9eea-d1d9d2bab7ba |
| 3c. Clara's reply to the counter held, not sent | PASS | eschold_0632ce5d-76a5-47fe-9a72-ff4e49489b01 |
| 3d. Yes by text → office note "said yes — please prepare the lease" with rent, term and start date | PASS | RP4-yes-note.png; note id 77d10fb1-2dc3-4e2a-a76d-8cbbe9f1a854 |
| 3e. Both notes use the coworker-note frame (one sentence, "Open the renewal" link, signed Clara, small logo, no footer) | PASS | same two screenshots |
| 3f. Fairhaven reset: list waiting, no running workflow, nothing queued to the bench, office email restored | PASS | RP4-final-state.json |
| Follow-ups filed, not blockers | 🟡 | #20003 (a yes after a counter leaves the record in review), #20004 (no holding text after a counter) |


Fede saw the prototype and said go (2026-10-14 night); legend dropped (not asked for). Shipped as PR #19881, merged 03:25Z, in production by 04:38Z. Verified live, headless screenshot of the real renewals page at 04:40Z (cards only shown; the list below them carries resident names).


Prototype record, for the trail:
| Before | After | |
|---|---|---|
| Big number | — / 0% / — / — | 0% on every month |
| Card heights | 137 / 167 / 137 / 137 px | equal (167 px) |



Why the dash existed: the renewed % only counted people who had answered; with no answers it was blank and drew as a dash. The fix shows 0% until someone renews. The renewal rate used elsewhere is unchanged.
Written for an agent. Every claim carries its source; nothing is summarized. Line numbers are from the 10/10 checkout c383d08ff0 unless noted; origin/main is ahead, and only one row changed (the "team is looking at this" text, #18564).
File key: AS renewal-auto-start.ts · WF workflows/renewal-workflow.ts · ACT activities/renewal.ts · TR/ER/RR renewal-orchestration/renewal-{text,email,reply}-review.ts · TOOLS agents/clara/lib/agent/tools/renewal/handlers.ts · SB/OB/ST/BGATE/RLR renewal-batch/{scan-batch,open-batch,settle-batch,batch-gate,release-render}.ts · HT/HRE/BG escalation/{held-text,held-reviewer-email,bake-gate}.ts · NOTIFY leasing/renewal-notify.ts · JOBS integrations/sqs/agent-jobs.ts · TW integrations/twilio/client.ts · VOICE integrations/voice/initiate-outbound-call.ts · SCS escalation/supervised-call-state.ts · CHAIN modules/building-module-chain.ts · SRH modules/supervised-reply-hold.ts · PE agents/clara/lib/messaging/process-envelope.ts · HOLD leasing/renewal-holdover.ts · REM leasing/renewal-reminder-sms.ts · SMS leasing/renewal-sms-template.ts · PMSW pms/writers/renewal.ts · LR app/api/leases/[leaseId]/renewal/route.ts · RECAP renewal-orchestration/recap-sms.ts.
Modes in code: Off is an explicit false for leasing.renewals (company switch, building row {enabled:false}, or building not in PropFlow). A company with nothing stored is Live (is-module-enabled-for-org.ts:41-43). Supervised = on plus a 'drafts' marker at company or building (:99-107; write-building-module.ts:15-21). Both need the auto-start arm (AS:414-430), the building opt-in (AS:765-772), the sending arm plus autonomousRenewalEnabled, checked before any Supervised hold (ACT:830-857). Held = saved for approval; parked = held until the list is decided, no 24-hour timer.
| # | Off | Supervised | Live |
|---|---|---|---|
| 1 Daily check | skips the building; nobody told (AS:719-735, 797-803) | opens as Live; monthly list once a month and right after a switch into Supervised (AS:737-760; OB:35-44; renewal-flip-scan.ts:1-9); list to reviewers by email plus Slack and the page (OB:46-62; HRE:101-112); month-to-month never on it (SB:144-145) | starts inside the window; board only (AS:2072-2260) |
| 2 AppFolio offer | never (JOBS:251-270) | Clara paperwork: day 0, before approval, robot prepares and sends to the portal (AS:2257-2259; JOBS:313,360,586); no Supervised check (JOBS:251-284; ACT:2896-2945); comments say AppFolio emails the tenant (pms-adapter.ts:474; AS:1857-1859). Team paperwork: never; PropFlow saves its own offer (AS:2140-2160; WF:3113-3115, 3334) | same, per sender |
| 3 Offer text | refused at the door, stamped held_module_off, nobody paged (ACT:1108-1125; TW:1077-1100) | held; parked with no expiry if on a pending list (TR:94-110; held-message-rule.ts:64-76); released at once if the list is approved (TR:112); plain 24-hour hold if on no list (TR:100-111); Slack (building channel → company → #alerts) and the page only (BG:179-210; HRE:105-108) | day 0 outside quiet hours (ACT:815-1000) |
| 4 Offer email, letter | refused, stamped, no page (ACT:2044-2089, 2344-2368) | same hold and park (ER:56-90; ACT:1906-1911, 2242-2290); on release the words are rewritten but the AppFolio letter PDF saved with the hold stays attached (RLR:119-130); email only to tenants with no phone (renewal-channels.ts:56-63); letter only under Clara paperwork (WF:3741) | day 0 (ACT:1758-2400) |
| 5 List approval | no list (SB:70-92) | approve: rent/term/concession written to the lease, parked messages rewritten and released (ST:14-61; RLR:52-152); "no" on a lease closes its parked messages as rejected (ST:66-97; BGATE:69-90); reject the list rejects all (ST:44-50); none touch AppFolio; a settled list takes no more decisions (ST:84) | no list |
| 6 Reminders day 2/9, 60/30/15-day nudges, MtM warning | refused for a running cycle, nobody paged (ACT:1612-1621) | each held (ACT:1473-1505; WF:3961-4133); released with the decided numbers if the list was approved (TR:112; ST:29-40); else 24-hour hold; on expiry reminders stop, board "needs you", PM page muted (WF:4178-4190; NOTIFY:251-292); on reject same with no page (WF:4191-4201); the scan's MtM warning is re-held after an unapproved expiry (AS:2765-2811) | on schedule |
| 7 Term change, portal link | tools refuse (TOOLS:519-527) | portal link, recap, after-call recap: 24-hour hold not tied to the list (TOOLS:376-399; RR:92-125; RECAP:254-276); term change under Clara paperwork writes the lease and AppFolio at once, only the text is held (TOOLS:1805-1880; LR:930-960); under team paperwork handed to the escalation tool (TOOLS:1748-1761) | sent at once (TOOLS:401-422; LR:962-980) |
| 8 Clara's reply | not sent; #alerts post naming the building (RR:166-171, 217-260; TW:1086-1093) | held when about the renewal, routed to Renewals, or the topic check fails or exceeds 6 s; general replies send (SRH:1-40, 103-131; classify-reply-topic.ts:146-190); texts held for everyone except staff (PE:402-423); emails only at a company marked live (SRH:69-90); newer reply supersedes (RR:208; held-reply-supersede.ts:18-27); after 24 h closed, Slack "the team has the thread", tenant gets nothing (HT:457-472); main adds "Got it, the team is looking at this" on a second text (#18564) | sent |
| 9 Tool actions behind a held reply | refused | run at once: yes/no saved and signalled (TOOLS:605-687, 948, 992-1040); escalation emails the building inbox (TOOLS:1095-1141); term change to AppFolio (TOOLS:1805-1880); only the texts are held (TOOLS:376-399) | same, texts send |
| 10 Yes, then 14-day signature wait | refused | yes saved; no PM email (TOOLS:961-963); once AppFolio shows the tenant signed, PM gets "ready for your signature" reminders, not stopped by Supervised, only sandboxes skipped (pm-action-reminder-renewal-bridge.ts:34-87; pm-action-reminder-copy.ts:186-201); no countersignature in 14 days: board "needs you", page muted (WF:1970, 2097-2164); #18548 mutes only the scan's held-renewal page (page-pm-for-held-renewal.ts:103-112) | same plus the 14-day page by email and text |
| 11 No | refused | intent and reason saved; workflow ends "intent to vacate" (TOOLS:992-1040; WF:2238-2240); no PM email, no AppFolio write (TOOLS:1052-1054); Clara points to the portal notice (TOOLS:1047-1050); fallback page muted (renewal-decline-delivery.ts:254-266) | same; fallback page goes |
| 12 Counter or unanswerable question | refused | email only to the building's own inbox, no company fallback, not stopped by Supervised (TOOLS:68-91, 442-452); case only if the building names an owner (TOOLS:1144-1166, 1203-1209); workflow escalation page muted (TOOLS:1353-1355; WF:2262-2264); a plain question adds a timeline line (TOOLS:852-920) | same email and case; the workflow page goes to renewal contact → building inbox → company owner, plus a text (NOTIFY:127-142; pm-contact-email.ts:96-133) |
| 13 Renewal call | door refuses, no retry (VOICE:446-449; ACT:2744-2750) | per-module choice; "calls go to the team" (default when unset) = no call; "Clara answers calls" dials on day 0 before the list is approved (SCS:1-50; VOICE:490-521; WF:3897-3905); recap text held (RECAP:254-276) | dials day 0 unless voiceCallEnabled is false; on by default (renewal-channels.ts:50-55; ACT:2521-2620) |
| 14 Month-to-month rollover | skipped (HOLD:149) | needs proof the warning reached the tenant; the warning is held so the rollover waits; then AppFolio is written with no further approval (AS:2765-2811; HOLD:179-188); office notice follows the Team notices module (renewal-holdover-notify.ts:151-180) | rolls over when armed (HOLD:91-95); under team paperwork never written (HOLD:84-90) |
| 15 AppFolio sync | same in all modes and senders: "Renewed" closes, "tenant signed" updates, "prepared" fills an empty offer; never reads mode or sender (PMSW:45-75) | ||
| 16 Notice to vacate filed | all modes; the workflow ends "declined" or a declined record is created (NTV:1-35, 139-150); nobody at the customer emailed; an unmatched notice alerts engineering once a day (NTV:58-72) | ||
| 17 Send-door backstop | renewal-send-guard.ts only stops double sends; Off refused (TW:1077-1100); Supervised refuses an unapproved resident text and alerts engineering (TW:1124-1150); email door same (company-live-gate.ts:435-466); voice same (VOICE:490-521); if the mode can't be read, the message sends (TW:1127-1129) | ||
| 18 Per-building override | company Off is a ceiling (CHAIN:170-183) | under an "on" company the building row wins; a building "On" is Live under a Supervised company (write-building-module.ts:15-21; CHAIN:196-248) | switching a building Off mid-cycle doesn't stop the workflow; later messages refused and stamped, tools refuse, replies post to #alerts (ACT:1108-1125; TOOLS:519-527; RR:166-171); a failed AppFolio prepare pages nobody and closes the cycle (ACT:3053-3057, 3844-3851) |
Unverified by the inspection: that AppFolio emails the tenant on prepare (code comments only); what happens to messages already held when a building is switched Off; what Clara tells the tenant when the escalation reached nobody; whether customer staff can see the PropFlow Slack channel.
| Item | Clara (default) | The office |
|---|---|---|
| Setting | building first, then company; unset means Clara; locked for the cycle at start (paperwork-sender-chain.ts:1-23, 128-135; TOOLS:1742-1748); a failed read returns null and the robot runs (:142); the building rung has no writer (:185) | same |
| AppFolio prepare | day 0, prepared and sent to the portal (AS:2252-2259; JOBS:313,360) | none; PropFlow saves its own offer and treats it as prepared (AS:2140-2160; JOBS:271-284; WF:3113, 3334) |
| Every signer needs an email | yes, for the portal invite | skipped (AS:1856-1867) |
| Offer text | "Review and sign in your resident portal: [link]" plus a letter line | "Our office will send over the renewal paperwork for you to sign" (SMS:55-62) |
| Reminders, nudges, MtM warning | portal link | "…our office will send over the renewal paperwork…" (REM:33, 105-165, 235) |
| Letter | AppFolio PDF by text | none; "Resend letter" refused (WF:3741, 2582-2586) |
| Term change | lease write + AppFolio term change + confirmation text | escalation tool with the requested term (TOOLS:1748-1801) |
| Month-to-month rollover | written to AppFolio when armed | never written; warnings still go (HOLD:84-90) |
| Close-out | AppFolio sync | identical (PMSW:45-75) |
| 14-day PM reminders | "…agreed to renew… just needs your signature" (pm-action-reminder-copy.ts:186-201; WF:2157-2163) | identical wording |
| Reply prompt | signing step in the portal | "the office will send over the renewal paperwork", no portal step (#19039, merged 10/12); the send_offer_sms recap still appends a portal link (#19041) |
No renewal block in org.settings (data/types.ts:15460-15489). Company renewal policy lives in registry rows ATTACH#setting#renewal.*. The arm row CONFIG/RENEWAL_ARMS is one row for all customers.
| Key | Level, type, default | Set where (who) | Read | Class |
|---|---|---|---|---|
| renewal.offerTerms (rent rule, max increase, terms, mtmPremium) | company registry (registry/keys.ts:1209-1238) + building RENEWAL_POLICY# row; absent = refuse | onboarding RenewalOffersQuestions → PUT /api/settings/renewal-policy, customer until go-live then 409 (route:119); /settings/renewals read-only (client-page.tsx:51); staff RenewalPolicyCard.tsx:122; building editor PropertyDetailClient.tsx:818 → PATCH /api/properties/[id]/knowledge, customer, no lock | foldRenewalPolicy company-chain.ts:116 (building wins; broken building never inherits :197); facts.ts:400 | policy |
| offerTerms.voiceCallEnabled | bool; absent = On (facts.ts:189-206) | staff card; building editor RenewalPolicyEditor.tsx:539; onboarding never asks; not on /settings/renewals (managed-settings.ts:59-85) | renewal-channels.ts:46 | capability |
| renewal.eligibility | company registry (:1239-1259) + building row; four different balance defaults (facts.ts:33-41) | same doors; maxAccountBalance never asked (renewal-drafts.ts:69-80) | company-chain.ts:116, :209 | policy |
| renewal.autoStartDays → building renewalAutoStartDaysBeforeLeaseEnd → legacy renewalOutreachInitialDays | int; 90; company 14-180, building 1-365 | company only via the PUT; building /settings/renewals → POST leasing-settings, customer | renewal-auto-start-chain.ts:83; renewal-auto-start.ts:483, :503 | policy |
| renewal.paperworkSender | company registry (:1276-1291) + building rung; 'clara' | 'team'; default clara | onboarding or Settings, customer before go-live; staff card :110; building writer has no callers (paperwork-sender-chain.ts:185) | paperwork-sender-chain.ts:128-135; refuseIfPaperworkSentByTeam :167-178 | policy |
| heldMessageReviewers['leasing.renewals'] | org.settings (data/types.ts:16242); staff or vendors; empty | staff only: PUT /api/admin/companies/[id]/held-message-reviewers (ModuleReviewersRow.tsx:38, :99) | held-message-reviewers.ts:29-34; scan-batch.ts:177 | policy |
| Reminder cadence D+2/D+9, nudges 60/30/15 | code constant; the doc at renewal-workflow.ts:949-961 says 48h/5d | nowhere | renewal-workflow.ts:3935-3936, :4086-4093; followup-registry.ts:428-449 'fixed' | rule |
| renewalContactEmail / renewalContactPhone | building leasing settings (:17324, :17327); email falls back to propertyEmail | no UI | renewal-notify.ts:127-131; pm-action-reminder.ts:512 | policy |
| renewalExecutionCcEmails | building (:17364) | /settings/property, customer | renewal-execution-notify.ts:122-132 | policy |
| Letter MMS | no key; always fires | nothing | renewal-channels.ts:1-23 | capability |
| Monthly list | no key; rides Supervised | nothing | scan-batch.ts:71-77; batch-gate.ts:28 | capability |
| enabledModules['leasing.renewals'] | org.settings (:15498); absent → platform row → all on | staff: /admin/customers/[id] → /api/admin/modules | resolve-module-entitlement.ts:144 | rollout |
| moduleModes[...]='drafts' + moduleSupervisedCalls | org.settings (:15511, :15549); absent = Live; calls absent = 'team' | staff, same door | is-module-enabled-for-org.ts:99-107; resolve-module-entitlement.ts:318-340 | rollout |
| leasing.renewals.module + building.in_propflow | building registry (:1176-1197); absent = inherit | staff (building-switches.ts:166) or scripts; customers only during onboarding (:151) | building-module-chain.ts:160; renewals-entitlement.ts:47 | rollout |
| claraLive | org (:16079); must be exactly true | staff: PATCH /api/admin/companies/[id]/clara-live | clara-live.ts:240; email only (email/client.ts:1570); locks the company policy (route:119) | rollout |
| autonomousRenewalEnabled | building flag (:3960); false | staff Arms tab /admin/dev/access-inspector?tab=arms → PUT /api/admin/arms; the editor toggle was removed (RenewalPolicyEditor.tsx:665-670); the knowledge PATCH writes only an audit copy (dynamo/renewal-policy.ts:113-119) | renewal-auto-start.ts:497; autonomous-gate.ts:67; skipped when a PM opened the renewal (activities/renewal.ts:200-202) | fix-shaped |
| Arm autonomousSending + env RENEWAL_AUTONOMOUS_SENDING; arm autoStart | arm row (:17682, :17677) + env; false | scripts/set-renewal-arms.ts; Arms tab read-only | autonomous-gate.ts:42, :58; activities/renewal.ts:831, :853; arm-store.ts:163; renewal-auto-start.ts:423 | fix-shaped |
| autonomousHoldoverEnabled + arm holdoverConversion + env | building flag (:4175) + arm (:17680) + env; false | flag: Arms tab; arm: script | renewal-auto-start.ts:502, :1525-1556; holdover-gate.ts:36, :52 | fix-shaped |
| Arm lists: workflowOwnedDispatch.propertyAllowlist, stableWorkflowIdentity.rollbackPropertyIds, autoStartExcludedPersonIds | arm row (:17703, :17747, :17816) | script only | arm-store.ts:237, :281, :216; renewal-auto-start.ts:716, :775-785 | fix-shaped |
| Schedules renewal-auto-start-daily, renewal-cohort-walker-daily | Temporal pause state | scripts/temporal/upsert-renewal-auto-start-schedule.ts | config/automations.toml:297-324 | fix-shaped |
| renewalLapseDigestEnabled | building (:17357); false; names its own removal trigger (:17351) | scripts/set-property-lapse-digest.ts | renewal-auto-start.ts:635 | fix-shaped |
| RENEWALS_MODULE_DEFAULT_ENABLED | code constant true; repeats the registry default | n/a | renewals-module-route.ts:76, :100, :125, :140 | fix-shaped |
| Env: RENEWAL_ARM_CACHE_TTL_MS, RENEWAL_TASK_QUEUE_OVERRIDE, ELEVENLABS_RENEWAL_AGENT_ID, TWILIO_MESSAGING_SERVICE_SID | env | deploy | arm-store.ts:58; temporal/client.ts:139; renewal-worker.ts:105; initiate-renewal-call.ts:59-61; activities/renewal.ts:2215 | fix-shaped |
| Test gates: phone-registry kinds, TEST_PROPERTY_IDS, DARK_FEATURE_BENCH_IDS, isTest | code + config | code change only | test-scope-recipient-guard.ts:46, :78; test-property-ids.ts:79, :122, :132; renewal-auto-start.ts:1189-1197 | fix-shaped |
Override semantics: module On/Off, the company is a ceiling (resolve-module-entitlement.ts:216; building-module-chain.ts:174-184); Supervised vs Live is not a ceiling, the nearest row wins (building-module-chain.ts:204-209, 240-247; write-building-module.ts:86-94); staff "Turn on" starts Supervised (module-row-actions.ts:74-94). Not switches: patched() replay markers; the per-renewal PM pause (activities/renewal.ts:213); renewalHorizonDays (display); Lease.evictionPending (no writer). Retired: RENEWAL_AUTO_START_ENABLED, TEMPORAL_ACTIVITIES_EFFECT_MODE, TEMPORAL_LIVE_PROPERTY_ALLOWLIST, RENEWAL_OUTREACH_KILL_SWITCH.
Production reads on 10/12 (read-only probes, scratchpad ws-ready/a.ts, d.ts, e.ts): Western Slope org_c42d9150… module enabled=false, stored mode null, company policy {rentStrategy market, terms [12], mtmPremium 150, voiceCallEnabled false, autoStartDays 90, paperworkSender null}, 90 buildings all state=off, line +19708220641 everywhere, PM inbox leasing@westernslopepm.com everywhere, reviewers [], claraLive true, moduleSupervisedCalls {maintenance: live}, autonomousRenewalEnabled true on 0 of 90, holdover flag 0; arm row {autoStart true, autonomousSending true, holdoverConversion true}; Camellia's one building has the flag on. Logins at Western Slope: 8 (Kat and Jay among them).
Origin. 9/28 standup (#transcripts, raw), Fede: "besides on and off there's also another layer… a mode where we're reviewing, human in the loop… for a week or a few days we're still reviewing every reply, that's what I did with leasing… then you turn it fully on… i don't know long term we're gonna continue to do that." Same thread Fede asked to centralize module flags; Gera: on/off "is not a simple binary"; Gera's Gatekeeper design that day: "the 'few days of review' step used when leasing launched". Trail: ADR-0139 (accepted 9/28, amended 9/29 and 10/1, the name "Supervised"); drafts design page 9/29 (decision b90675488); Gera's PRs #13909, #13903, #13906, #14894. Ancestors: collections approval gate (ADR-0125, 8/6), renewal review switch (#13009), Camellia bake gate (#6654, 8/30, "TEMPORARY").
Designed. Only what goes out waits ("anything inbound we always record", Gera 10/5); actions happen right away, only the message waits (Gera 10/1). "Someone on the customer's team presses send" (design 9/29; 10/4 announcement); Gera 10/6: "goes through our Slack, and then we can just thumbs up it". Expiry 24 h then it dies unsent; a newer draft replaces the older (Gera 9/29, "a little bit of urgency" 10/5). Calls cannot wait: Supervised treats a call like Off unless "Clara answers calls". Length "about a week" (Gera 10/5); Fede 9/30: "first week it's supervised… we review it on Slack, click approve, send it". Optional: "we can skip it… go straight to live" (Gera 10/6). Exit: no rule; staff press "Make Live". The onboarding playbook's older review-mode bar: replay shows 0 "do not send", 90% sent as-is, Fede decides.
Built (10/10 checkout). Only 'drafts' is stored (types.ts:15511); six modules honor it (drafts-allowed.ts:34-38). Holds every automatic message to a person: residents, prospects, vendors, handyman, crew, owners, staff notices (AdminBuildingsCard.tsx:58; supervised-reply-hold.ts:103-155). Never held: emergencies, urgent jobs, person-started messages, approvals, escalations, login codes, general replies. Approve re-checks, sends through the normal door with an approval id; the door refuses unapproved Supervised sends (drafts-backstop.ts:16-54). Only a stored Supervised holds; an unreadable setting sends (resolve-module-entitlement.ts:296-298). 24 h expiry (held-message-max-age.ts:17); MtM warning re-held with a fresh 24 h (renewal-auto-start.ts:2797); renewal-list items never expire (held-message-rule.ts:73). Slack card to the building channel else #alerts (bake-gate.ts:197-209); mention hard-coded to Fede (review-gate-mention.ts:26) until per-module customer reviewers (ADR-0141, 10/8). Company plan is a ceiling for Off only (building-module-chain.ts:177-183); a building Live beats a company Supervised (building-module-override.test.ts:294); staff "Turn on" starts at Supervised; customers see only on/off.
Drift. Scope: "anything that goes out to tenants" (Gera 10/6) became "every recipient" (10/4). Reviewer: announced as the customer's team, built as PropFlow staff; customer reviewers came 10/8 (ADR-0141), only staff set the mode. "Short" not enforced: no timer, no since-date, no nudge, no exit rule; standing Supervised on both test companies (testing playbook 10/9) and Collections "nobody on Live" (Gera 10/1; 0 Live / 77 Supervised on 10/2). Renewals ride on the state by Fede's 10/9 ruling: the list opens only in 'drafts' (scan-batch.ts:77, #18321); per-message reviewer emails off (held-reviewer-email.ts:108); PM paging off (#18548, #18552). Long-term talk: Fede 10/8, right after "eventually we'll not have that": customer reviewers are "more scalable, I think, long term… we would probably want that client too". Two hold systems share one queue: company "review mode" (Fede 9/19, "TEMPORARY") and per-module Supervised; mixed up in #western-slope 10/7. Regression: team notices defaulted to Supervised 10/4-10/6; Fede 10/6: "Camellia should be fully autonomous"; default now Live (types.ts:18530); stale comments remain (drafts-allowed.ts:32, types.ts:15552).
Verdict on Fede's five claims. Core modules: mostly (four core plus two send modules). Tenants and prospects: partly (every recipient). A week then Live: yes on intent, nothing in code. Temporary: yes for new modules; standing exceptions Collections, test companies, the renewals list; skippable. Outbound only: yes, inbound always recorded; catch: actions still happen. Suggested, not asked: decide whether Supervised is a timed soak (show days-in-Supervised) or a standing mode (then name the renewals list and Collections separately). This page takes the first.
Langfuse keys: Keychain service propflowai-prod (LANGFUSE_*). The 20:50Z text turn has no trace 23 minutes later; the email thread in the same minute has three. Likely cause: the flush at conversation-manager.ts:17421 is fire-and-forget and an empty reply returns the Lambda at once. The 7 "renewal_declined" hits since 9/1 are false positives (thinking text only); no traced text decline exists to compare. Control: the 20:42 "yes" turn (traces d22739cb, 83f66c1e): call 1 thinking plus renewal_accepted, no text; tool result {success:true, intent:"renew"}; call 2 "That's great news… You're all set for the 12-month renewal at $914/mo…" (the test tenant's prepared offer on Fairhaven). So tool-result wording is not the cause.
The conflict only decline turns have: prompt.ts:191 "Write your response TEXT first (before calling any tool)" and :198 "The text must appear BEFORE the tool call"; clara-delivery.ts:167 "text alongside a tool call… is NOT sent… Only your response AFTER all tool calls complete is delivered"; :173 the decline instructions "before going silent". Where the text dies: conversation-manager.ts:13888 restores the pre-tool text only if the final is exactly empty; a marker-only or whitespace final counts as non-empty; the salvage guard restores only URLs and dollar amounts; the strip at :13941-13942 blanks it; nothing re-checks. No NoReplySent log line, so the 13915-13918 branch did not fire. Not deliberate silence: no end_conversation (:13150), no guard CRITICAL; the video-only silent rule is at :13913. alertNoReplySent posts to #alerts through pageFede once per hour per conversation and cause; on a sandbox it is a console WARN only. Outcomes by post-tool output: exactly empty → pre-tool text sent; marker-only or blank → silent (this case); a short closer → sent without the notice instruction; a full rewrite → fine. The CI eval (evals/promptfooconfig-renewals-sms.yaml) is one model call with only the renewal block and cannot see this. Fixes: (A) prompt.ts:187-198 tool first, then the reply, keep the "AFTER A DECLINE" heading for renewal-prompt-block.test.ts:105-150, update the two decline cases in evals/datasets/renewals-sms.yaml:2655+; (B) conversation-manager.ts fallback on the cleaned text, then the last pre-tool draft, else noReplyAlert('empty_reply'); (C) await flushLangfuse briefly on the empty path. Scratch: scratchpad/lf/.
| Product | Decides terms | Sends | Handles replies | Paperwork | Human in loop | Integrations |
|---|---|---|---|---|---|---|
| EliseAI | not stated; offers via branded portal | 30/60/90-day touchpoints; SMS, email, voice | answers; "hands off to staff with full context preserved" | e-signature "runs automatically" | no approval step; renewal-likelihood dashboard | "integrates with existing PMS" |
| Colleen Lease AI | not stated | SMS, email, voice, chat before 90 days | not stated | not stated | not stated | Entrata (unverified) |
| AppFolio Realm-X | not stated | Resident Messenger renewal messages ("coming soon") | rent and term questions | not stated | "Performers" in Flows; a Lease Renewals Flow template | native |
| Entrata ELI+ | not stated | outreach on renewal-intent detection | not stated | native | ||
| Yardi Virtuoso | not stated | chat, email, text, voice | full conversation claimed | not stated | native | |
| RealPage AI Resident Agent | not stated | email/SMS reminders | not stated | not stated | "augments human efforts"; "transparency and control for human operators" | RealPage |
| Funnel Resident AI | "shares renewal options" | expiry notices, options, sign reminders | resident Q&A | not stated | Yardi, RealPage, Entrata | |
| Zuma (Venn, 9/22/2026, ~$50M) | not stated | renewal outreach, payment reminders | agent "owns" conversations | not stated | "seamless human backup" | not stated |
| Rentify (UAE) | not stated | renewal, lease generation, insurance, payments | not stated | lease generation | "approval workflows" | not stated |
| Frontdesk (add-on) | negotiates within "guardrails" | voice, SMS, email at 90/60/30/15 days | negotiates | portal or DocuSign | guardrails; audit trail | Yardi, RealPage, Entrata, AppFolio, Buildium |
| Hyly.AI, BetterBot | not stated | renewal drips and campaigns | not stated | |||
| Knock, Buildium, ResMate, LeaseHawk, Lula | no native renewal AI found | |||||
Sources and the full write-up: scratchpad competitive/renewals-competitors.md (session 1fcfe5de). Published results are vendor marketing (EliseAI's 9% from one case study; AppFolio's 20% from its own survey; HappyCo's +11 points with human support, n≈300, vendor-run).
RENEWAL NOTIFICATIONS: WHO IS TOLD, AND WHAT GOES QUIET Read-only code inspection of main at a54bb5c3de (2026-10-12 20:36Z). Nothing was run against production. No tenant or customer names below. Paths are under src/lib/ unless they start with agents/, src/app/ or lambda/. Short names: act = temporal/activities/renewal.ts; wf = temporal/workflows/renewal-workflow.ts; bake = domain/escalation/bake-gate.ts; held = domain/escalation/held-text.ts; door = domain/staff-reply/door.ts; batch = domain/leasing/renewal-batch; auto = domain/leasing/renewal-auto-start.ts; notify = domain/leasing/renewal-notify.ts; tools = agents/clara/lib/agent/tools/renewal/handlers.ts; sms = integrations/twilio/client.ts; mail = integrations/email/company-live-gate.ts. Modes: Off / S = Supervised ('drafts') / L = Live. "team" = paperworkSender 'team'. "unverified" = I could not confirm it in code. Merged 2026-10-12 (deploy times unverified): one reviewer email per hold to all reviewers, hello@ BCC (18:17Z); Slack card tags both PropFlow reviewers (16:16Z); plain-note list email (20:33Z, after the 20:26Z event). 10-10: no per-tenant staff page under S (#18548, #18552). "Tell the other reviewers when one decides" (#18998) is an open issue, not built.
THE SHORT ANSWER (why it feels like we send nothing)
WHO IS WHO (how staff addresses resolve)
TABLE 1. WHO IS TOLD (one row per send site)
| # | Trigger | Who is told | Channel / when | Off / S / L | team paperwork | file:line |
|---|---|---|---|---|---|---|
| 1 | Monthly list of renewals to approve | The company's chosen Renewals reviewers (setting heldMessageReviewers['leasing.renewals'], staff or vendors, each re-checked at mail time): ONE email to all, hello@ BCC. PropFlow Slack card tags both PropFlow reviewers (nobody at sandbox buildings). No reviewer chosen = nobody emailed; the renewal contact only fills the hold's "to" field | email, Slack card, page; first daily scan each month; never repeated, never expires | Off, L: no list. S: yes | none (list is per lease) | batch/scan-batch.ts :73-79,:100-110,:177-180; batch/open-batch.ts :53-63; domain/organizations/held-message-reviewers.ts :29-34; domain/escalation/held-reviewer-email.ts :113-114,:139-174; bake :506-526; domain/organizations/review-gate-mention.ts :34-42,:74-91 |
| 2 | Reviewer replies "approve" by email | The replier only: "Thanks, approved ... Everything else goes out as listed" (no hello@ copy). PropFlow's Slack thread gets "Customer reviewer answered". An edit-only reply gets "Recorded ... still waiting for your approval" | email; at once | S | none | door :245-254,:271-272; domain/staff-reply/batch-reply.ts :293-305; domain/staff-reply/answer-reviewer.ts :30-42,:60-92 |
| 3 | Reviewer approves on the page | Nobody. The page gets data back and one log line is written. No email, no Slack line (settle-batch.ts has no Slack or email call at all) | none | S | none | src/app/api/admin/escalation-holds/[id]/route.ts :198-226; bake :2625-2630; batch/settle-batch.ts :1-4,:29-76 |
| 4 | Other reviewers told when one decides (#18998) | Not built. Only the replier hears (row 2) | -- | -- | -- | door :271-272 |
| 5 | Offer text (Day 0) | The resident. Staff learn only through the list | SMS; Day 0, pushed past quiet hours | Off: not sent. S: held first (list approved = reviewed body goes out, no second approval; list open = waits; lease not on list = ordinary hold, 24h). L: sent | wording changes; no letter leg | act :826-1160; wf :3580-3610,:3836-3912; domain/leasing/renewal-orchestration/renewal-text-review.ts :70-113; batch/batch-gate.ts :1-90; domain/leasing/renewal-sms-template.ts :26,:55 |
| 6 | Offer email and letter | The resident. Email goes only when there is no phone number (with a phone the email step quietly skips). Letter (picture text) only when the PMS prepares paperwork | email, MMS; Day 0 | as row 5 | no letter leg; no PMS prepare wait; "Resend letter" refused | act :1773-1812,:2135-2226; wf :2577-2580,:3102-3108,:3728-3775 |
| 7 | Reminders (48h, +7d) and expiry nudges (60/30/15 days) | The resident | SMS; per ladder | as row 5; a renewal a person owns, or that escalated, is "held" with no send | wording changes | act :1296-1398,:1615-1631; wf :3950-4123; domain/leasing/renewal-reminder-sms.ts :105,:140,:235 |
| 8 | Outbound renewal call | The resident (voice) | Day 0 | Off: no call (the door refuses, the workflow is told dispatched_failed, info log). S: no call by default ("calls go to the team"); it dials as Live only if the customer chose "Clara answers calls". L: dials. The workflow throws the result away | -- | act :2728-2731,:2744-2751; domain/leasing/renewal-orchestration/initiate-renewal-call.ts :97-104; integrations/voice/initiate-outbound-call.ts :438-488,:490-521; domain/escalation/supervised-call-state.ts :8-10,:43-50 |
| 9 | Month-to-month warning | The resident by text. The office is paged only if no offer is prepared and the lease is not lapsed; if an offer exists the office is not told it went out | SMS (+ email to office); retried every daily scan | Off: refused at the door, info log. S: each warning held (never on the list). L: sent | rollover never written, so no conversion | auto :2518-2954 (:2764,:2925-2945); domain/leasing/renewal-orchestration/mtm-warning-send.ts :141-259; domain/leasing/renewal-holdover.ts :84-90 |
| 10 | Clara's replies, and texts Clara sends mid-chat (offer recap or portal link; the term-change confirmation is row 23) | The resident, unless held. S: renewal-topic replies are held; the resident hears nothing except one fixed "Got it, the team is looking at this." if they text again while it waits. Reviewers: PropFlow Slack card only; the customer's staff can find it only by pulling the /review "Held emails" feed. Non-renewal replies send | SMS; on each inbound | Off: unverified. S: held. L: sent | -- | domain/modules/supervised-reply-hold.ts :103-131; agents/clara/lib/messaging/process-envelope.ts :466-514,:768-801,:1032-1036; domain/escalation/held-reviewer-email.ts :106-108; domain/escalation/held-reply-ack.ts :4-25; tools :376-399; src/app/api/held-emails/route.ts :29-57; domain/escalation/held-email-rows.ts :26-37 |
| 11 | Resident texts yes or no | No staff message. The workflow is signalled (best effort); a "no" ends the renewal with outcome intent_to_vacate and an audit entry. The event that would page the PM when no live renewal exists has no listener in the text Lambda | -- | S: that page would be swallowed | -- | tools :599-678,:984-1073,:1054-1056; wf :2230-2231; act :4329-4345; domain/automations/handlers/decline-renewal-on-clara-signal.ts :46-116; domain/leasing/renewal-decline-delivery.ts :159-191,:213-282; domain/pms/events/bus.ts :20 |
| 12 | "Needs a person" page for one resident (19 reasons, e.g. counter-offer, said yes but never signed, countersign overdue, offer expired unapproved, prepare failed) | PM contact chain: renewalContactEmail, else property email, else company escalation owner; plus a text to renewalContactPhone; hello@ copy | email + SMS; once per lease and reason per 24h | S: swallowed for every caller (only reason "unknown" alerts engineering). L: sent | -- | notify :251-300,:327-348,:423-465,:497-501; act :3246-3256,:3298-3300; wf :2257-2258; domain/leasing/renewal-escalation-copy.ts :52-130; domain/leasing/pm-contact-email.ts :1-20 |
| 13 | Held renewal page (opted out everywhere, held for review, no contact details, signer has no email, tenant transferring, no offer price). Also fires when staff click Send offer or Approve; they also get a plain error on screen | PM contact chain, as row 12 | email + SMS; once per lease and reason per 65 days | S: swallowed before the once-slot, info log. L: sent | -- | domain/leasing/page-pm-for-held-renewal.ts :6-14,:103-129,:154-162; src/app/api/leasing/renewals/outreach/route.ts :278-325; src/app/api/leasing/renewals/approve/route.ts :481-509; domain/leasing/renewal-escalation-copy.ts :71-85 |
| 14 | Resident asks for a person or counter-offers (Clara's renewal_escalate) | The property's own main email only (not the renewal-contact chain), hello@ copy | email; during the chat | Off: refused. S: NOT held (declared "no module", so the Supervised email net is skipped; only the company-live check applies). L: sent. Code-read, runtime unverified | -- | tools :68-91,:444-455,:1075-1082,:1355-1357,:1467-1477; mail :376,:476-515 |
| 15 | Matter and decision request to the escalation owner | The escalation owner, only when the PROPERTY itself names one; otherwise no matter at all | Held when the company review switch (reviewOutboundEmails, needs company live) is on and the property is not autonomous; else emailed | -- | tools :1195-1261; domain/escalation/open-matter.ts :796-872; domain/properties/escalation-bake-gate.ts :1-10,:38-55 | |
| 16 | Resident signed, PM must countersign (14-day wait) | The PM, email only: the FIRST reminder, and only if the company opted in (default off). Reminders two onward are retired. No text. At day 14 the workflow escalates: PM page | email; once, then the page at day 14 | S: page swallowed. L: sent. Off: unverified | countersign path under team: unverified | temporal/activities/pm-action-reminder.ts :427-476,:517-543,:650-664; wf :1890-1971,:2154-2159; auto :1481-1497 |
| 17 | Lease executed ("renewal done") | The office: renewalExecutionCcEmails (first is To), else renewalContactEmail, else property email; signed PDF attached; hello@ BCC | email via Team notices | Off: nothing, counted as handled. S: held; an approval email to the Team notices reviewers (none chosen = PropFlow Slack card only); if it expires unapproved (24h) the drain holds it AGAIN under the same id, and each re-hold writes a fresh pending row, a new Slack card and a new reviewer email (no dedupe found), so reviewers are re-nagged about daily until a person acts; only a person's reject ends it (bake :464-530; domain/escalation/team-notice-send.ts :124-143). L: sent | -- | act :3902-3985; domain/leasing/renewal-execution-notify.ts :129-155,:322-332,:392-436; domain/leasing/send-pending-notice.ts :111-124,:166-175; domain/escalation/team-notice-send.ts :108-143; domain/notifications/observer-copy.ts :66-72 |
| 18 | Lease rolls to month-to-month (holdover) | (a) The office gets a heads-up email, same chain as row 17, hello@ BCC. (b) The PM contact chain is paged only if the lease lapsed while held for review ("held lapsed"), as row 13. Nobody else hears of a rollover | (a) email via Team notices, next daily scan. (b) email + SMS | (a) as row 17 (re-hold after expiry: unverified). (b) S: swallowed; L: sent | rollover never written, so (a) never fires (inferred) | domain/leasing/renewal-holdover-notify.ts :151-247; auto :1403-1440,:1600-1645 |
| 19 | Leases-ending digest (ending soon, resident never answered) | The PM contact chain (renewalContactEmail, else property email, else company escalation-owner email); no hello@ copy. One email per property per business day; nothing on empty or closed days | email via Team notices | Property switch renewalLapseDigestEnabled, default OFF. Then Off: nothing. S: held for the Team notices reviewers (re-hold after expiry: unverified). L: sent | -- | domain/leasing/renewal-lapse-digest.ts :1-32,:285-331; auto :625-637,:2385-2417; data/types.ts :17390 |
| 20 | Notice to vacate arrives from the PMS | Nobody. The renewal stops, the resident is stamped "Notice to Vacate filed", pending reminders just stop. Registered in the AppFolio-sync runtime | none; on sync | no Renewals-module check in the handler (grep); one upstream is unverified | -- | domain/automations/handlers/decline-renewal-on-ntv.ts :139-154,:302-336,:406-489,:572-581; domain/automations/registry.ts :12-14; lambda/appfolio-sync/handler.ts :339-340; wf :2092,:2227-2228 |
| 21 | AppFolio shows the renewal finished outside Clara | Nobody. Renewal closes "resolved externally"; conflicts go to an audit note | none | no Renewals-module check in the handler (grep); one upstream is unverified | -- | domain/renewals/external-apply.ts :1-84; wf :1487-1518 |
| 22 | Sent / Not sent / Expired / Withdrawn lines | PropFlow's Slack thread for the hold only (in the property's activity channel, else the company's front-door channel, else #alerts); never the customer's reviewers | Slack; after each event | S | -- | domain/escalation/held-sent-note.ts :97-156; held :466-482,:796-816; act :1225-1235; bake :185-212 |
| 23 | Resident asks for a different term and the AppFolio robot applies it | The resident gets a confirmation ("your renewal is now an N-month term"). Staff are not told | SMS; when the robot reports back | Off: refused at the door. S: held (a hold that cannot be written is logged and NOT sent; nothing retries after the 24h expiry). L: sent | -- | src/app/api/leases/[leaseId]/renewal/route.ts :516-523,:931-965,:967-985; data/types.ts :22849-22854 |
| 24 | Renewal letter text bounces for good at the carrier (bad or unreachable number: Twilio 30003, 30005, 30006) | PM contact chain, as row 12, told the number on file is wrong | email + SMS; once per lease per 65 days | S: swallowed. L: sent. team: no letter, so never | -- | domain/leasing/renewal-orchestration/letter-mms-status.ts :35,:61-63,:86-134,:185-190; domain/leasing/page-pm-for-held-renewal.ts :103-129 |
| 25 | A renewal call ends with no decision (voicemail, missed, busy, rejected) | The resident gets a recap text with the offer and portal link. Staff are not told | SMS; once per call (30-day key) | Off: skipped (info log). S: held (a hold that cannot be written is logged and NOT sent). L: sent | not checked (unverified) | domain/leasing/renewal-orchestration/recap-sms.ts :104-138,:250-282,:294-325,:385-399 |
| 26 | Engineering alerts | PropFlow only (Sentry, #alerts, bake-alert email): stuck-renewal sweep every 15 min; dead-workflow check hourly; lapsed lease with a cycle on file; warning not sent; countersign stalled; prepare-failed retries; AppFolio refused the eligibility read 3 days running (never the PM); SendGrid bounces | Slack, email, Sentry | all modes; the stuck sweep has no Supervised awareness | paperwork_by_team never alerts | domain/renewals/stuck-saga-sweep.ts :121,:145,:193-197; src/app/api/cron/renewal-workflow-health/route.ts :1-114; auto :1182-1215,:1481-1497,:1714-1743; domain/renewals/retry-failed-prepare.ts :1187-1287; src/app/api/sendgrid/event/route.ts :308-332,:503-529; domain/leasing/renewal-read-refused-skip.ts :20-62 |
TABLE 2. SILENT OUTCOMES (the only result is a log line or an unread field)
| # | Silent site | Resident sees | Record shows | Staff / reviewer sees | PropFlow sees | file:line |
|---|---|---|---|---|---|---|
| 1 | Opt-out refuses a renewal text (blocked at every opt-out scope; a START to one company reopens only that company; scope defaults to "all") | Nothing arrives | Workflow told dispatched_failed; hold stays "approved"; no undelivered flag; send claim released | Reviewer was told "approved, Clara is sending it now"; the list page still says offers go out; no Not-sent notice | One warning log line | sms :896-905; act :1126-1135; domain/compliance/suppression-gate.ts :217-225,:256-259,:339-366; domain/compliance/suppression-matrix.ts :12-13,:134-136; domain/staff-reply/answer-reviewer.ts :30-42; src/app/(workspace)/admin/escalation-holds/[id]/RenewalBatchView.tsx :155-158 |
| 2 | Root cause of row 1: no opt-out check before the hold is made, and renewals call only the "Sent" half of the reporter that tours and prospects use for "Not sent" | Same | An opted-out resident's text is held, listed and approvable | Looks normal | Nothing | domain/leasing/renewal-orchestration/renewal-text-review.ts :70-113; act :1148,:1717,:2083,:2434; temporal/activities/tour.ts :399; domain/escalation/approved-hold-not-sent.ts :1-150 |
| 3 | Opt-out lookup fails | Nothing (outreach fails closed) | dispatched_failed | Nothing | Sentry fatal: the one loud case | domain/compliance/suppression-gate.ts :231-239 |
| 4 | Test-scope guard (a sandbox or test building may reach only our own numbers and inboxes) | Nothing | Text: dispatched_failed. Email: BLOCKED ledger row | Nothing | Warning log | sms :971-990; mail :337-360; notify :371-381 |
| 5 | Company-live gate (org_not_live): email door only, the text door has none | No email | BLOCKED ledger row; a transient "hold" | Nothing | Info log | mail :482-514; integrations/email/send-durability.ts :130; agents/clara/lib/messaging/process-envelope.ts :483-487 |
| 6 | Module Off at the door (text, call) | Nothing | Text stamped channelOutcomes.sms "held_module_off" (reminders: no stamp). Call: dispatched_failed plus a refusal row; S with the default call choice is refused the same way | Nothing (the company's own choice) | Info log | act :1115-1125,:1615-1621,:2744-2751; sms :1038-1111; integrations/voice/initiate-outbound-call.ts :438-521 |
| 7 | Supervised safety net refuses a send that carries no approval | Nothing | Refusal row | Nothing | Sentry fatal | sms :1114-1160; mail :443-473 |
| 8 | A step skips but tells the workflow "sent": PM pause, robot disarmed, building not enabled, resident already declined, already tried this cycle, quiet-hours backstop (same for reminder, email, letter, call) | Nothing, now or later | Nothing | Nothing | Warn or info log | act :830-880 (quiet hours :873-879),:1296-1352,:1773-1812,:2135-2175,:2539-2620 |
| 9 | Other "not sent" returns: no phone, no offer prepared, no outbound line, approved hold no longer valid, carrier error | Nothing | Workflow ignores the result: Day 0 just starts the 24h clock; the nudge ladder is marked done even if it failed | Nothing | Warn log ("no line" also alerts via the resolver) | act :886-893,:937-941,:985-990,:1152-1162; wf :3836-3912,:4121 |
| 10 | Renewal email bounces | No email. The bounce-to-text fallback is built for prospect threads (renewal mail: unverified) | Workflow told "failed", used only to block "Resend letter"; ledger corrected; hold's Sent line flipped to Not sent | Nothing | #alerts page (engineering) | src/app/api/sendgrid/event/route.ts :308-332,:341-389,:549-575; wf :2317,:2536-2545; bake :2996-3055; agents/clara/lib/email/ndr-bounce.ts :391-621,:666-753 |
| 11 | Held offer, reminder, reply, call recap or term-change confirmation expires at 24h (no workflow waits on the last three, so nothing retries), or a newer draft replaces it | Nothing | Hold closed; workflow told dispatched_failed; the older draft is "withdrawn" quietly | S: nothing (the PM page for an expired offer is swallowed). L: PM paged | Slack thread line "expired" or "withdrawn" | wf :2452-2470,:4160-4171; held :466-482,:796-816,:824-903; act :1178-1240; data/types.ts :22849-22854 |
| 12 | List rejected or lease struck: every parked hold closed "rejected" | Nothing | Workflow ends with "no page, our reviewer already knows" | Nothing beyond their own reject. The workflow's comment assumes PropFlow's own Slack reviewer rejected (wf :4176-4180); a customer reviewer who rejects is told nothing more (inferred) | Nothing | batch/settle-batch.ts :62-64; batch/batch-gate.ts :75-89; wf :4172-4182 |
| 13 | Lease not on the list (appeared after it opened, or its pointer is unreadable): falls to an ordinary per-send hold | Nothing unless someone approves within 24h | Hold, expires as row 11 | No email, no list line | Slack card only (no mention at sandbox buildings) | batch/batch-gate.ts :23-39; batch/scan-batch.ts :100-110; domain/escalation/held-reviewer-email.ts :106-108 |
| 14 | List never approved | No offers, reminders or nudges | Holds stay parked; workflow rechecks every 24h; the list never expires | No reminder to reviewers | Slack bumps at 1h and 3h only; the stuck sweep skips OFFER_PREPARED | wf :2451-2456; bake :3261-3272,:3297,:3320-3326; held :1173-1184; domain/renewals/stuck-saga-sweep.ts :193-197 |
| 15 | No Renewals reviewer chosen for the company (a company with no Team notices reviewer parks the executed-lease, holdover and digest emails the same way) | No offers (all parked) | List exists on a page | Nobody emailed; no one on the customer side is pointed at it | Slack card only | domain/escalation/held-reviewer-email.ts :113-114; bake :524-526; domain/escalation/team-notice-send.ts :140-162 |
| 16 | Approval cannot be applied (pointer flip fails, or one release fails) | Offers stay parked | Page says approved; workflows still parked | Page says approved | Sentry exception (logError) | batch/settle-batch.ts :34-37,:69-71; platform/logging.ts :129-148 |
| 17 | Under S every per-tenant staff page is swallowed: expired offer, counter-offer, said-yes-never-signed, countersign stall, held renewal, bad-number letter, undeliverable decline, prepare failed (PM-fixable) | n/a | "supervised: no per-tenant page"; once-slot released | Nothing; the list covers only leases on it, as of opening | Only reason "unknown" alerts engineering; the stuck sweep waits 72h | notify :233-300; act :3298-3300; domain/leasing/page-pm-for-held-renewal.ts :103-120; domain/leasing/renewal-decline-delivery.ts :254-282; domain/renewals/stuck-saga-sweep.ts :145 |
| 18 | Workflow ends quietly: outreach exhausted, lease gone, wrap-up (AppFolio close-out or PM-decided month-to-month), countersign wait ends | n/a | Audit-only "outreach_exhausted"; no outcome notice | Nothing | Nothing | wf :1487-1518,:1627-1648,:2154-2159,:4006,:4120,:4235 |
| 19 | A step throws or a signal fails | Nothing | A thrown send becomes dispatched_failed; approve-signal failure flags undelivered with a Not-sent line; reject-signal failure is log only | Nothing | Warn log; dead workflows caught hourly (engineering) | wf :3819-3835; held :729-733,:780-782; act :2395-2513; src/app/api/cron/renewal-workflow-health/route.ts :1-114 |
| 20 | Clara's own text tool reports "sent" even when the door refused | Nothing, though Clara may say she texted | Tool result sent:true | Nothing | Door warning | tools :401-423,:1558 |
| 21 | Executed-lease, holdover or digest email has no address, or does not deliver; or the digest switch is off | -- | No address: unmarked, retried every tick, no alert. Not delivered: logError. Switch off: info "went unreported" | Staff never learn the lease signed, rolled, or is ending | Sentry only on not-delivered | domain/leasing/renewal-execution-notify.ts :301-307,:425-433; domain/leasing/renewal-holdover-notify.ts :155-161,:214-224; domain/leasing/renewal-lapse-digest.ts :285-294,:335-347; auto :2385-2394 |
| 22 | Month-to-month warning refused (no phone, opt-out, quiet hours, no line, person owns it) | No warning | No receipt, retried each scan; conversion blocked while unwarned | Nothing | One engineering alert, only if the lapsed lease has a cycle on file | auto :1178-1183,:1714-1719,:2518-2721 |
| 23 | Clara's loop returns an empty reply | No reply | Log "No outbound ... empty reply" | Nothing | Log | agents/clara/lib/messaging/process-envelope.ts :646-658 |
| 24 | Offer or reminder text accepted by the carrier, then fails or is undelivered | A late or missing text | Lease field channelOutcomes.sms = sent_undelivered or sent_failed (shown on the renewal page). The log says the email fallback is "retired" and the reminder ladder "will retry" (to the same phone). The status route's comment still claims an email fallback fires | Nothing. Only a letter to a bad number pages anyone (Table 1 row 24) | Info log | act :752-791,:1136,:1633; domain/leasing/renewal-orchestration/sms-cascade.ts :1-20,:112-121; src/app/api/twilio/status/route.ts :101-116 |
| 25 | Letter text blocked by a carrier filter (30004, 30007, 30032, 30034), or its text leg is refused so the picture leg is skipped, or only the picture fails | Nothing, or the words without the PDF | letterMms outcome and detail stamped on the lease: a pull-only line, no push (only the bad-number codes page) | Nothing | Info log | domain/leasing/renewal-orchestration/letter-mms-status.ts :36,:46-48,:176-190; domain/leasing/renewal-orchestration/send-renewal-letter-mms.ts :295-326,:380-411 |
| 26 | After-call recap text skipped: no phone, no tenant or building on the call, already done for this call, no offer rent on the call, or no outbound line | No recap | Nothing; the per-call key is already used, so no second try | Nothing | Info log (a missing line also alerts through the resolver) | domain/leasing/renewal-orchestration/recap-sms.ts :109-138,:199-202,:223-235 |
| 27 | After-call recap text refused at the door (opt-out, test building) but recorded as sent | Nothing | An activity entry "Sent SMS recap to ..." and an info line are written without checking the door's answer (no message id comes back). Code-read; not seen at runtime | Nothing | Info log | domain/leasing/renewal-orchestration/recap-sms.ts :294-325,:385-399 |
| 28 | Term-change confirmation cannot be sent: no tenant, no phone, no outbound line, or the door refuses | Clara promised a confirmation; none arrives | Warning or info log only; the term change itself is already saved | Nothing | Warn or info log | src/app/api/leases/[leaseId]/renewal/route.ts :510-515,:843-880,:995-1001 |
| 29 | AppFolio refused or timed out the eligibility read for a lease | The renewal does not start that day | A "read unavailable" marker; every daily scan retries; never a PM page, never the 65-day once-slot | Nothing | ONE engineering alert (email and fatal log) after 3 days in a row | domain/leasing/renewal-read-refused-skip.ts :1-9,:20-62 |
THE THREE EVENTS FROM TODAY
3. THE REVIEWER'S VIEW AFTER THEY APPROVE THE LIST
UNVERIFIED
Read-only history for tonight's design doc. Every quote was machine-checked against the source text (dictation garbles left as spoken; tenant names and phone numbers removed). Bold rows are turning points.
Coverage: team-meeting transcripts in Slack reach back to 2026-04-26 (Slack access worked). Fede's own typed words on renewals in his sessions start 2026-08-31. Earlier design comes from docs, ADRs and PRs. Fede's last session note is a design doc still in progress.
Mar-Apr May-Jun Jul-Aug Sept Oct 1-12
BUILD -> POLICY AT -> TRUST: only say -> ONE ENGINE, -> CENTRALIZED CUSTOMER:
screen, CAMELLIA, what AppFolio month-to-month Supervised, paperwork
robot autonomy on confirms is the end split, reviewer list,
state; WS joins then "levels"
Renewals began in March as a screen plus automatic texts, and by April a browser robot created the offer inside the customer's own AppFolio. At Camellia the intent was prepare and send, with people only for exceptions, and by July 'its already on'. The summer was about trust: say only what AppFolio confirms, let AppFolio win any disagreement, and fall back to month-to-month. In September two renewal engines became one (9/3), and on 9/5 Fede ruled that a tenant who stays on month-to-month is not re-offered. Western Slope then arrived with a different shape: a central manager who renews by hand, wanted a stoppable heads-up, and was pitched "autonomous within policy". The design went further than they asked: hold every message until approved, a monthly reviewer list, and a setting for who sends the paperwork. On 10/12 Fede called these layers 'too complex' and recast them as levels of autonomy: Supervised is a one-week soak, and Camellia is the top level.
| Date | Source | What was decided or said | What it changed |
|---|---|---|---|
| 2026-03-09 | git log, via one-doc history | First commit naming renewals: Renewals tab Phase 1. By 3/17 it adds auto-outreach and a manual Send Outreach button for demos. | Renewals starts as a screen plus automatic outreach, built for demos, before it is a workflow. |
| 2026-04-12 | PR #62 | First auto-send: "Auto-send for good-standing tenants — renewalAutoSend setting (OFF by default, safe for prod)". | Offers can go out with no manager click, for good-standing tenants only. |
| 2026-04-16 | memory ruling, via one-doc register | Fede authorizes autonomous-renewal testing at the Willows test property only: "prepare AND send with no pre-ask". More than one month of rent owed means a person reviews. | First statement of intent: Clara acts without asking. First (loosest) balance rule. |
| 2026-04-22 | PR #366; memory rulings | The guard that blocked writing to Camellia's AppFolio is removed. Fede: "DO NOT USE THE NATIVE LEASE TEMPLATE. KEEP CAMELLIA TEMPLATE." and "ALL TERMS MUST BE CREATED… never guess or pick… exactly what the policy says." | Clara's robot creates and sends the offer inside the customer's own AppFolio with the policy's exact terms. This is the "Clara sends the paperwork" path. |
| 2026-04-26 | founders, dashboard redesign (transcript) | Sean's first spec of what a manager should see: "How many of those have renewed? How many of those are waiting a response? And what's my renewal percentage for the month?" | Renewals are measured as a funnel for the asset manager before the automation exists. |
| Date | Source | What was decided or said | What it changed |
|---|---|---|---|
| 2026-05-02 | founders, Denver whiteboard (transcript) | Fede's first end-to-end picture: "We call them to explain the terms, we text them the renewal letter. And then they can just log into their portfolio. And sign in." (The transcript says portfolio; he means the resident portal.) | The original vision: Clara calls and texts, the tenant signs online, no staff step. |
| 2026-05-07 | founders, renewals demo (transcript) | Early renewals are supervised. Sean: "if it says review, it means, like, that that's ready for the manager to review and send." Same day he asks: "If we send the renewal offer and they don't respond to it, what's our follow-up? Like, 48 hours?" | A manager reviews and sends each offer at first. The first reminder is set at 48 hours. |
| 2026-05-11 | docs/autonomous-renewals/policy.md | The first written design, for Camellia: "Renewals were paper-based until Clara turned on (~April 2026)." It proposes a daily job scoring each tenant on a ten-gate scorecard. | The original paper design. The build is reverted a day later (5/12). |
| 2026-05-12 | PR #881 | The overnight policy build is reverted whole. Reasons: simplify step skipped, bot review missed a bug, internal jargon shown to owners. | The policy engine stays small. A process lesson, not a design reversal. |
| 2026-05-19 | founders standup (transcript) | Fede's escalation rule: "When someone doesn't answer a renewal for a week, then I escalate to human." | Silence for a week goes to a person. Later reversed twice (7/17 quiet wrap-up, 8/13 never give up). |
| 2026-05-20 | founders standup (transcript) | On renewals that involve collections or eviction, Fede: "I would say at least 50% of renewals in Camellia are like that. We're like, we probably won't be able to automatically." | The expectation in May: about half need a person. By 7/13 he reports about 90% going out on their own. |
| 2026-05-21 | memory ruling, via one-doc register | Camellia's property manager gives the rules: balance, not lateness, is the disqualifier; more than 2 months owed goes to a person; her preferred hand-off channel is SMS, not email. | First customer-given policy. The owed-rent line moves from 1 month to 2 months. |
| 2026-05-22 | PR #1307 | Eligibility "v6": two checks (months owed, late payments) and only two results, AUTO_RENEW or HITL_REVIEW, with no score. A five-gate scoring prototype is dropped. | Eligibility becomes auto or a person. |
| 2026-05-24 | ADR-0025 update; PR #1376 | Renewal timers and retries moved to Temporal Cloud on 5/14. On 5/24 the old send switches are retired: one fail-closed gate, a text needs the global arm and the property flag, and ships disarmed. | Every send fails closed. |
| 2026-06-03 | ADR-0046 (decided on the JP/Camellia accounting call) | A lease that lapses unsigned converts to month-to-month at the property's premium, the office is emailed on every signed renewal, and the reminder warns about the roll. Register: "Holdover is fully autonomous". | Month-to-month becomes the built-in fallback. The first office notifications exist because accounting asked. |
| 2026-06-03 | accounting-gaps call, Camellia and JP (transcript) | Origin of the month-to-month fallback. Sean: "if they haven't signed it, but the lease expires, then Clara will go in and change it to month-to-month in AppFolio." Fede adds that the tenant should be told: "now you're month to month." | An unsigned offer at lease end rolls to month-to-month, and the tenant is told. Written up the same day as ADR-0046. |
| 2026-06-03 | accounting-gaps call (transcript) | Why accounting wanted it. Fede: "people were signing renewals after they expire already. […] your lease expires, and then it's like, oh, 15 days later, you sign." A double charge the month after a renewal had surfaced the day before (6/2). | The fallback fixes leases signed after they expired and the double charges that followed. |
| 2026-06-04 | ADR-0047 | The 6/2 plan to delete the saga is overruled: "The RenewalSaga DynamoDB entity is retained as the durable identity, audit, and read-model anchor for a single renewal cycle." | One stored record per renewal cycle stays; the workflow writes it. |
| 2026-06-08 | prod-learnings standup (transcript) | After a small test send with one unclear reply, Fede: "what I'm gonna do is, after this call, I'm gonna turn on the autonomous renewal, so I don't have to approve them anymore. They're just. start going out by themselves." Rule stated: under one month outstanding sends; above it, "it's flagged for human review". | Manager approval ends in Fede's plan. The 6/22 ADR notes Camellia was still holdover-only then, so autonomous offers began later. |
| 2026-06-09 | memory rulings, via one-doc register | An emailed notice to vacate is valid: "Do NOT re-argue the 'is email legally valid notice' angle — Fede decided it is." Also no manual comms outside the pipeline. | Notice by email counts as notice. |
| 2026-06-16 | founders standup (transcript) | Fede on Camellia's office: "Renewals are fully automated. All they have to do is click one button to sign. Before, they took three hours by paper. […] it takes them, like, two, three days to click one button." | The slow step is the office's countersign, not Clara. It drives the 7/22 reminders. |
| 2026-06-22 | memory ruling, via one-doc register | "Do NOT add a legal/eviction gate to the decision engine. Legal signals are too flaky; late-payment count is the deliberate proxy." | Eligibility stays simple. Revisited 7/20. |
| 2026-06-23 | ADR-0066 option C (Fede); PR #2573 | The eligibility verdict now gates the text: "Fails closed — a missing verdict holds, never sends blind." On Camellia's live group, read-only, 11 would-be sends to people who need a person fell to 0. | A text goes out only when the rulebook says auto. |
| Date | Source | What was decided or said | What it changed |
|---|---|---|---|
| 2026-07-07 | memory ruling (PR #3257) | "Just have it on", "no more flags": the retry switch is deleted and retry becomes unconditional. | Early form of the later rule that fixes never get a switch. |
| 2026-07-07 | founder chat | Fede ahead of the Camellia session: renewals "need to start asking them to review the ones that are not auto sent because of payment history". | First sign of a customer reviewing the renewals Clara holds back. |
| 2026-07-08 | founders with Camellia staff (transcript) | Gera asks Camellia's Joanna the "who sends" question: "Would you want it, Joanna, to go to you, where maybe you send it, um, or you confirm it, and then it would send, or do you want us to just send it on your behalf?" No answer in the transcript. | The send-or-confirm choice is put to a customer for the first time. It returns for Western Slope on 10/8. |
| 2026-07-15 | ADR-0091 | "Treat the PMS as the system of record for tenancy facts (lease terms, offer status, charge schedules, scheduled increases, move-outs)." The first version has a manager confirm any conflict. | Start of the rule that AppFolio wins. |
| 2026-07-16 | walkthrough with Camellia staff (transcript) | What a flag means. Sean: "it's not gonna send out the renewal until you review it and approve it." Joanna gives her own rule: "if they owe, like, 2 months or more, they're getting sent a 10-day, and they're not being offered a renewal". | At Camellia, held renewals wait for the office's approval. The two-month line is the customer's own. |
| 2026-07-16 | walkthrough with Camellia staff (transcript) | Kenya on countersigning: "I think we were saying to countersign within 72 hours". Fede describes Clara's cadence: a monthly text, then "if you don't renew, we're going to move you to month to month. […] And that has a $100 premium." | A 72-hour promise by the office. The monthly reminder plus month-to-month warning is described to the customer. |
| 2026-07-17 | PR #3985 (ADR-0091 addendum) | When AppFolio shows a renewal handled, the workflow wraps itself up: "No contradiction → no human at all." The body calls it founder-ratified: less clicks, less reviews. | The manager-confirm step is cut (finished on 9/3). |
| 2026-07-17 | PR #4020 (ADR-0100) | A fourth way a renewal ends: "the PM decides not to offer a renewal and lets the tenancy continue month-to-month." "No tenant comms anywhere." | A manager can roll a lease with no offer and no message. |
| 2026-07-22 | ADR-0108 (PRs #4322, #4374) | One decision spine: the daily scan, the staff buttons and the watchers all run the same gate pipeline. Thirteen fixes land that day. | One rulebook for who may be contacted. |
| 2026-07-23 | memory ruling, via one-doc register | "its already on": autonomous renewals at Camellia are on by intent. Policy v2 is locked at 2 months owed, 6 late payments, 25 days of grace; a dry run moved auto-approval from 59.3% to 92.0%. | Camellia is the live, autonomous reference customer. |
| 2026-08-03 | founders standup (transcript) | How outreach felt in early August. Fede: "Just the renewal engagement is pretty low. […] someone says you're a scammer. […] Because it is a random 800 number." On 8/6 he describes the order: "We call them, leave a voicemail, then text them a renewal offer letter." | Calls and a toll-free number get little trust. This leads to text first, no opening call (9/28). |
| 2026-08-06 | Camellia standup (transcript) | Fede after a tenant asked for a new-tenant special: "there should be a renewal policy now. Anyone that asks, we should say, hey, this is for new movies only. The AI should learn that." Sean: "it's for new move-ins only. No, not renewals." | A rule from the customer becomes a policy Clara follows. |
| 2026-08-13 | founder voice memo | Autonomy as a principle: "remove work away from the human as much as possible escalate as little as possible when we escalate we create a policy and learn and the next time we don't". | Each escalation should become a saved policy. Echoed 8/18 and again on 10/3 (company brain). |
| 2026-08-13 | Camellia call (transcript) | A real counter-offer, read out by Sean: "A thousand is currently being advertised on the Camellia website for new tenants leasing studio floor plans similar to mine. If possible. I greatly appreciate if a comparable rate could be considered for my renewal." Camellia's staff also note Spanish-speaking tenants "came down, they were like, who is Clara". | Clara does not negotiate; it goes to the office. The 8/3 findings page confirms "never negotiate" held. |
| 2026-08-18 | founder voice memo | Fede on approvals: "i just don't think like having a dashboard where they go review conversations and approve things that i just don't think that will ever happen". Instead, staff replies become policy: "what's a one-off exception versus like a general policy". | Approval moves off dashboards to email and text. The 10/8 to 10/12 reviewer list comes back to a page as a backup. |
| 2026-08-25 | Situs demo (transcript) | Situs's Eileen: "if you're calling and texting them, and it's not going back through the API to be captured by AppFolio." The 'Hugo' label (it covers more than one voice) adds: "How do we hone in on the unknown still, where, like, they haven't made a decision?" | Customers want every renewal contact written back to AppFolio, and a plan for the undecided. |
| 2026-08-25 | Situs demo (transcript) | A fear and the answer (labels mixed). "If we fat finger a renewal rate on our, you know, market rent […] catastrophic problem." Reply: "there's a process where you first start with a human in the loop reviewing everything. We don't start going autonomous where it just sends out stuff." | Human-in-the-loop first for a new customer. The 8/26 follow-up draft: "Our philosophy is to earn autonomy rather than turn everything on at once." |
| 2026-08-31 | Fede session a566db0c | After a delinquent tenant was sent a holdover reminder: "i originally wnated the holdover to be attached to the renewal workflow not standalone" and "i dont want a standalone rogue process". | Holdover must live inside the one renewal workflow. Starts the "one engine" thread. |
| Date | Source | What was decided or said | What it changed |
|---|---|---|---|
| 2026-09-02 | Fede session 28bc997e | On a built-but-gated behavior: "this should always be on, remove the feature flag andd deploy". | Early form of the no-switch-on-live-behavior rule. |
| 2026-09-02 | standup (transcript) | Fede's onboarding idea: "hey, do you want to send autonomous renewals out, or do you want, like, someone to check it first? […] after, like, a month of checking it, you, like, say, okay, I'm good to go." | First statement of check-first, then autonomous, as a customer's choice. The generic gate is covered elsewhere. |
| 2026-09-03 | architecture page; PR #6902 | Two starters ran Camellia renewals at once (11 cases, 5 a month early, PM pages sent twice). Fede picks "one starter, one owner, fix in place." The second starter is deleted because "a switched-off-but-present starter is exactly the kind of thing that gets accidentally re-armed." | One daily scan is the only thing that starts a renewal. |
| 2026-09-03 | architecture page (cadence ruling, dated 08-31 there) | Reminder cadence: "reminder 3 times like we do today with leases. business days only. once per day max." | Three reminders, business days, once a day. Not applied to every case (see tensions). |
| 2026-09-03 | memory ruling | When AppFolio already shows a renewal handled: "this is wrong. if it was updated in appfolio we should just follow the signal, no one is going to manually review." | Clara follows the property system's own signal. No confirm queue. |
| 2026-09-03 | Fede session 28bc997e | Seeing 5 renewals started a month early: "i dont undertadn why there are 2 engines" and "i never approved or revieewed any new architecture". Then: "i want to never worry about this again". | The two-engine decision. One engine, finish the migration (Option B, merged that day). |
| 2026-09-03 | Fede session 28bc997e | When the system saw AppFolio already updated: "if it was updated in appfolio we should just follow the signal, no one is going tmanually review". | AppFolio facts are followed, never confirmed by a person. |
| 2026-09-03 | Fede session 28bc997e | On the call that refused to talk about a renewal because a name did not match: "we should just say the offer" and "remove the rule and add evals". | Outbound renewal calls drop the identity gate. |
| 2026-09-04 | PR #7101 | Two Camellia leases that ended 8/31 were skipped until 9/4 because "our own unanswered offer blocked the month-to-month fallback that exists to clean up unanswered offers." Accepted-but-unsigned tenants are never rolled. | The roll-over now runs for unanswered offers. |
| 2026-09-04 | Fede session 28bc997e | On a missed notice to vacate: "dont we have an automation to set NTV on appfolio when someone submits notice?" and "everything shoud be automatic". | Notice to vacate is set in AppFolio with no human step. |
| 2026-09-04 | Fede session 28bc997e | On the lease-expiry notice to the office: "we want to reduce noise in the mailbox, but i think we could group together and give a headsup to the PM of this a day before they exprire (business day)". | Grouped heads-up instead of per-tenant pages. Reappears 10/10 as "i said no per tenant emails". |
| 2026-09-04 | Fede's chat thread, voice note (speaker unlabeled) | Fede's retro: "I feel like I've regressed in a lot of areas of the product, adding all this complexity, guards, warehousing, […] that is kind of collapsing and made things worse. So I'm thinking we're going to go back to basics. And remove everything and go all autonomous again for Camellia." | Camellia goes back to fully autonomous; the added guards come out. The same day Option B is chosen (see 9/3 and 9/5). |
| 2026-09-04 | Fede's chat thread | Why Camellia: "we already know all the policies, we're in the weeds, so we don't really need to be asking [Joanna] anything. And besides, she's not going to answer anyways." The fancier checks move to Situs: "people like [Eileen], she's going to be super engaged". Gera agrees: "it's better to say something than to keep tacking onto this giant queue that we've been building on human review". | Review only makes sense where the reviewer answers. Camellia's office does not; Situs's and Western Slope's must. |
| 2026-09-04 | Western Slope demo (transcript) | What Western Slope was told and assumed. Sean: "we like to reach out, like, 90 days before the lease is expiring, and we give them a renewal offer. […] they accept, and then we… we send the, um, the paperwork automatically." Jay: Clara will "send renewals out in the renewal module". | The original promise: Clara sends the paperwork itself inside AppFolio. Western Slope does not renew that way (9/9). |
| 2026-09-05 | ADR-0046 banner; PR #7137 | After three Camellia leases roll to month-to-month, Fede: "i dont want to offer anything, just roll mtm." The re-offer code is deleted. | Month-to-month is the end state. No second offer. |
| 2026-09-05 | memory ruling | "Silence is not approval." A behaviour fix ships behind a per-property gate, off by default; an unanswered decision is a hold. | One of the three rolled units had a human case open. |
| 2026-09-07 | founder chat | Fede's pull of Western Slope's AppFolio: "Renewals. Flat. Eight of twelve renewed at the same rent. Where rent moved, the median increase was 2.1%." | Western Slope's real pattern is flat rent, which later shapes the first-list rent rule (D6). |
| 2026-09-09 | Western Slope onboarding (transcript) | Jay: "we also use the leasing function for our renewals, as opposed to the renewals function, right? So we're utilizing a handful of amendments in the leasing function". Fede: "if we're consistent and you guys have, like, one process for your whole portfolio, and, like, maybe one template, like, one addendum, you know, those kinds of things simplify." | Western Slope does not use AppFolio's renewal tool. The paperwork path built for Camellia does not fit them. |
| 2026-09-09 | Western Slope onboarding (transcript) | Order of rollout. Jay: "if we're going to focus leasing and then renewals and then maintenance, I think that's fine. […] I mean, renewals is gonna be a big piece". Sean on 9/4 had said maintenance, then leasing, then renewals. | The customer's order wins for now. On 10/1 Fede runs renewals first for revenue. |
| 2026-09-17 | Camellia standup (transcript) | Of 5 renewals due: "3 did not renew, 1 transferred, and 1 is… we just don't have their contact info". Joanna on one resident: "I don't think we should offer them right now, anyway." Kenya asks for a 'transferred' outcome "so it shows that they stayed". | Camellia's staff set exceptions by hand and want transfers counted as stays. |
| 2026-09-18 | Denver-portfolio call (transcript) | Sean's phased plan: "we'll start with the leasing, and then when you guys are ready, we can turn on maintenance, and then when it's ready, we can turn on renewal." | Renewals planned last at a second centralized customer. |
| 2026-09-23 | one-doc, Goal section | Target: "Western Slope live on renewals by Friday 2026-10-02, and invoiced for them." Design that day: "Kat inspects that list before anything goes out", Clara sends the texts, replies wait in Slack. | First design for a centralized team. Origin of the reviewer list. |
| 2026-09-23 | team meeting (transcript) | Fede on the swap: "the Maintenance phone line, like, they already have that contract till next year." Then: "Yeah, I think renewals make sense." On why he takes it: "renewals, I feel like, needs a lot of fine-tuning." | Renewals moves ahead of maintenance for Western Slope, and Fede takes it on himself. |
| 2026-09-28 | one-doc | "The channel is decided: text first, no opening call." 29 calls reached 2 residents and produced 0 decisions. Smallest turn-on is 8 steps, starting with a company-level renewal policy. | Voice stops being the opener. Policy moves up to the company. |
| 2026-09-28 | PR #12897 (dark) | One company renewal policy that every property inherits, nearest wins. Why: "A company with no per-property policy (e.g. a newly onboarded portfolio of single-family homes) opens zero renewals, because every property would need its own policy typed in." | Policy moves from per building to per company, which a centralized team needs. |
| 2026-09-28 | founder chat | Fede on new modules: "we turn on a module and then for a week or a few days we're still reviewing every reply so that's what i did with leasing". Also: "a few days of like sanity check before we turn on autonomous". | Review-first for any newly enabled module. Seed of Supervised. |
| 2026-09-29 | founder chat | Fede's audit of how Western Slope renews today: "a person decides the new rent by hand. AppFolio's automatic increase is set to $0 everywhere." Offers are "almost always a single 12-month option" and go "about 53 days before the lease ends". | The real baseline: hand-set rent, one 12-month offer, late. Opposite of Camellia's engine-set terms. |
| 2026-09-30 | Western Slope check-in (transcript) | Jay on judgment calls: "there's certain tenants that have bad payment history that we just want to go month-to-month with, we don't want to lock them in." And on non-renewals: "We need to schedule a move out in that folio". | The customer wants month-to-month as a tool and move-out scheduling automated. |
| 2026-09-30 | Western Slope check-in (transcript) | Sean's pitch: "Clara will just send out the renewals based on those policies. And then if anyone is outside of those policies […] it'll just email you guys and say, Hey, this tenant asked for this." Fede adds: "we send the contract out autonomously". | Pitched as autonomous within policy, with exceptions to staff. Seven days later the customer is placed on Supervised. |
| 2026-09-30 | Western Slope check-in (transcript) | Sean on holds: "if they're more than 60 days past due, we're not gonna… we're gonna hold it for review." | Hold rules were first pitched as a rule on balance. Jay later said balance above zero (10/7). |
| 2026-09-30 | Western Slope check-in (transcript) | Fede offers review-first: "instead of just sending it autonomously, we review it on Slack, click approve, send it." Gera: "we probably want to be, like, within the hour to two hours." Fede: "it's not, like, urgent. You know, you have three months". | A Slack approve step is floated. Renewals are slow enough to wait, so the reviewer list was possible. |
| Date | Source | What was decided or said | What it changed |
|---|---|---|---|
| 2026-10-01 | Western Slope go-live page (D1 to D4) | Fede confirms week-one placeholders: offer 90 days before lease end; a habitual late payer is held for a person; same rent; Cheryl gets questions and counter-offers. | First concrete Western Slope settings, pending their answers. |
| 2026-10-01 | PRs #14897, #14899 | Supervised holds renewal texts at the resident's building. "a reply that cannot be held is escalated with its words, never sent live, never silently dropped". | The renewal side of the Supervised gate. Held, not sent. |
| 2026-10-03 | Western Slope go-live page, 10/3 plan | Turn-on planned for Monday 10/5. Known risk: "AppFolio emails the tenant the moment an offer is created. Supervised mode holds Clara's texts, not that email, so the Sunday list is the real gate." | The risk that drives the paperwork split a week later. |
| 2026-10-07 | PR #17243 | "One gatekeeper, one path (Gera, 2026-10-06)." The 9/28 company switch that held renewal texts is removed; 0 of 11 companies had it on. | Supervised becomes the one text gate for renewals. |
| 2026-10-07 | Western Slope questionnaire call (transcript) | What Sean tells the customer: "we will send a renewal offer to a tenant, and we'll follow up with them, uh, continuously until they respond." And: "If they don't reply by the expiration date, it just converts to month-to-month." | The cadence and the roll-over are explained to the customer. |
| 2026-10-07 | Western Slope questionnaire call (transcript) | Jay on timing and terms: "Clara opens each renewal 90 days before lease ends, yes. We offer a 12-month". On rent, Sean proposes: "we would just bring it up to market" using their spreadsheet. | The first customer-given renewal policy at Western Slope. |
| 2026-10-07 | Western Slope questionnaire call (transcript) | Jay on who is held: "I want to renew people at zero". Payment history does not matter if the balance is zero. | Eligibility at Western Slope is the balance, not late payments. Camellia's late-payment limit is switched off for Western Slope. |
| 2026-10-07 | Western Slope questionnaire call (transcript) | The customer's ask for control: Clara flags before each 90-day trigger, "and then if we haven't… […] If we haven't, you know, redirected her or told her no, then she goes ahead." Escalations: "Clara will build an agenda, we'll review the items she has escalated in our, you know, our weekly or monthly renewal meeting". | The customer asks for a heads-up it can stop, plus a meeting agenda. |
| 2026-10-07 | Western Slope questionnaire call (transcript) | Scope: "I think right now, Clara, building the templates is out of scope. […] the one page renewal could be in scope." Manual for now: "that's Lincoln and Courtyard Apartments." Questions go to "Kat, and she'll escalate to me if she needs to." | Lease templates stay with the customer. Two affordable-housing buildings stay out. |
| 2026-10-07 | internal call on rollout order (transcript) | Origin of the split. Fede: "the basic thing that we can turn on now to get. […] Started. Not the fully autonomous, fully fancy version." "Step one could be not even send the contract, just send the communication. […] Because half of their properties don't have a template." | Communication and paperwork become separate steps. |
| 2026-10-07 | internal call on rollout order (transcript) | Fede first proposes the customer's heads-up: "Send in a list. […] Of people that we're gonna renew, and if we don't hear otherwise, we'll just… […] Send it out." Gera: "we definitely would want to have some sort of supervised mode right now. Like, we wouldn't want to just send it out to tenants and be like, oh, good luck." | Same day, the proceed-unless-stopped list is replaced by hold-until-approved. |
| 2026-10-07 | internal call on rollout order (transcript) | Fede admits what is missing: "if they reply, oh, no, don't do it, like we would need to build that. […] We haven't built that." Instead: "these are the renewals, review them. […] Should we just link to, like, a review page?" Sean on default rent: "a flat or a 25". | The reviewer email with a review page is chosen because reply-by-email is not built. |
| 2026-10-08 | PRs #18017, #18039, #18040, #18041, #18058 | New setting for who sends the paperwork: "this is a NEW capability setting. The default is 'clara', which is today's behaviour." On the team path "the renewal runs as a conversation and leaves the paperwork to the customer's team." A replay of Camellia's real book is identical before and after (4 offers, 1 hold, 15 no action, 0 writes). | Talking to the tenant and sending the paperwork become two separate things, and Camellia does not change. |
| 2026-10-08 | Fede session f86757cf | The first statement of the split: "the customer isn't ready yet for fully autonomous sending out the leases. […] a way to switch it so that it only sends communications out, not the contract yet, and the team would still have to do the contract." | Origin of the paperwork-sender setting. Bias: "reducing new work as much as possible". |
| 2026-10-08 | Fede session f86757cf | "I don't want to necessarily make a mess here, but just have a way to kind of like slowly walk towards fully autonomous renewals." | The graduated path the 10/12 levels recast. |
| 2026-10-08 | Fede session f86757cf | On first scope: "for V1 I need a version we can finish in the next 24 hours" and "this might need a bit more thinking" (on the weekly heads-up and opt-out mode). | The heads-up mode Jay asked for was set aside. See Open threads. |
| 2026-10-08 | Fede session f86757cf | On proof: "willows is just the single property so not enough conffidence" and "we need to probably standarize and clean up actually not add more". | Leads to the testing playbook and two standard sandbox companies. |
| 2026-10-08 | founders standup (transcript) | Fede on today's Camellia flow: "renewals are like fully autonomous right in [Camellia] where we do everything. We decide, we send the offer and execute." Then: "I'm decoupling the send the document part from the communications […] your team does the paperwork, and once you're comfortable, we graduate you to paperwork". | Autonomy becomes a ladder a customer climbs. Camellia is the top. |
| 2026-10-09 | Western Slope go-live page | Approval cadence decided: one batch email on the 1st of each month, with no setting. Fede on the first sample: "very crowded, doesn't tell you who the tenant is." | The reviewer list becomes one monthly email. |
| 2026-10-09 | PR #18321 | The daily scan "opens ONE monthly batch per Supervised company as a held message and emails the company's Renewals reviewers through the existing held-message door." "Month-to-month (no end date) leases are not in the list (Fede 2026-10-09)". | The monthly reviewer list exists. Month-to-month tenants are left off it. |
| 2026-10-09 | Fede session 1fcfe5de | On approvals to staff: "I don't know if I like the one email per approval. […] it makes more sense to batch it so you know every I don't know if it's every month or every week". And on the timing: "I don't think we want a setting for this." | The monthly reviewer list is born. No setting for its timing. |
| 2026-10-09 | Fede session 1fcfe5de | On what the review needs: "let's not over engineer or over build. […] just basic ability to change things like you know the new rent at least". And: "we should not include month-to-month in it." | Review means renew yes or no and change the rent. Month-to-month tenants are not on the list. |
| 2026-10-10 | PR #18552 [urgent] | Incident after flipping a sandbox company to Supervised: "33 per-tenant pages to Fairhaven staff". "Only one of four callers carried the Supervised check. The shared sender had none." | Supervised never pages office staff per tenant, from any caller. |
| 2026-10-10 | Fede session 1fcfe5de | On finding per-tenant emails in the build: "i said no per tenant emails" and "why do they exist". | Per-tenant office emails removed (PR #18552). |
| 2026-10-11 | Fede session 1fcfe5de | On the build's email-first flow: "Well, isn't this a text experience? Primary?" and "is the email experience what we have in Camellia, or did you make this up?" | Tenant contact is text first; email is for the office. |
| 2026-10-12 | memory ruling (PR #19038) | Renewal texts lose the STOP footer: "renewal texts are not marketing". | Small wording rule. |
| 2026-10-12 | levels-of-autonomy page | "paperwork is no longer tied to Live (Fede, 10/12)". Levels 0 to 4 are presets of three settings; "who decides the terms" becomes its own setting; the Off/Supervised/Live gate becomes a one-week soak. | The newest design. |
| 2026-10-12 | Fede session 1fcfe5de | On review pages: "we would prefer one review page for all". | One customer review page; the admin page stays internal. |
| 2026-10-12 | Fede session 1fcfe5de | The reviewer list, 11:46. "we should have a way to list who are the people one person or multiple that review and approve […] renewals so in this case it's Jay and Kat so we should send a single email to both of them […] we also want to have a backup link that goes to a review page". | One email to a named list of reviewers, with a review page as backup. The MVP for Western Slope. |
| 2026-10-12 | Fede session 1fcfe5de | A tenant replied to a test text and nothing happened: "what hapenens if someones does want to renew" and "or if theys submit NTV on the website". Then: "for no, let me think about it more" / "dont build yet" / "lets design it". | The tenant-reply gap is named. Design before build. |
| 2026-10-12 | Fede session 1fcfe5de | The simplification, 14:55. "I think this is too complex and probaly need to simplifyi or consolidate concepts" and "im not sure we want to tie "live" mode with sending the paperwork or not". | Reverses the 10/8 ladder where paperwork was the last step of Live. Paperwork is its own setting. |
| 2026-10-12 | Fede session 1fcfe5de | On Supervised: "it's an in-between step and then the goal is to get everyone live right". | Supervised is a short soak, not a destination. |
| 2026-10-12 | Fede session 1fcfe5de | On levels: "levels of autonomy where the first level would be just sending out the communication. […] Camellia is kind of like the ultimate level where everything's automatic except negotiations." | The levels recast. Camellia is the top level, not a special case. |
| 2026-10-12 | Fede session 1fcfe5de | On the next step: "How do we step up a customer that might not be ready?" and "maybe these are just kind of like settings or something". | Levels may be settings. Still open (D5 on the levels page). |
| 2026-10-12 | Fede session 1fcfe5de | The expected notice-to-vacate reply: "Sorry to hear you're leaving or something like that. And then guiding them like, okay, the next step is to do a formal notice to vacate on your tenant portal". | Clara guides to the official notice in AppFolio, which triggers the other automations. |
| 2026-10-12 | Fede session 1fcfe5de | The plan for the week: "since we're on supervised mode I would expect at least for the first week or so that it will hold the message messages and then me and Hera would approve each one". "Hera" is a speech-to-text garble for Gera. | Week 1 Supervised with Fede and Gera approving. |
| 2026-10-12 | Fede session 1fcfe5de | "we would turn autonomous […] once the customer approves or changes or whatever they do, it just sends it out. And there's no uh, engineering in the loop. Anymore. That will be like by week two." | Week 2 goes autonomous on the customer's approval. |
| Topic | Earlier | Later |
|---|---|---|
| Re-offer to month-to-month tenants | ADR-0046 (6/3): "send a fresh offer for the next month" | Fede 9/5: "i dont want to offer anything, just roll mtm." |
| Approval before sending | Fede 9/3: "no one is going tmanually review" (about AppFolio facts) | 10/12: a named reviewer list approves each renewal. [inference] These fit if AppFolio facts need no review and owner terms do. |
| Autonomy for Western Slope | 10/7 Fede: "Send in a list. […] Send it out." (proceed unless stopped) | Same day Gera: "we definitely would want to have some sort of supervised mode right now." Decided 10/8: hold every message until approved. |
| Autonomy vs a queue (9/4) | Fede: "go back to basics. And remove everything and go all autonomous again for Camellia" | Gera, same day: "it's better to say something than to keep tacking onto this giant queue that we've been building on human review" |
| Paperwork tied to Live | 10/8 ladder: the team does the paperwork "and once you're comfortable, we graduate you to paperwork" | 10/12 Fede: "im not sure we want to tie “live” mode with sending the paperwork or not" |
| Switches | 9/2 Fede: "this should always be on, remove the feature flag andd deploy" | A per-building autonomous flag, arms, and a new paperwork setting exist; the levels page lists them under "Not settings: delete or fold" |
| Held messages | Supervised design: "A held message expires after 24 hours if nobody acts." | 10/12 levels page: "A held reply never dies silently." (design, not built; the 10/9 fix was parked) |
| Engines | 8/31 a separate holdover process was added; Fede: "i dont want a standalone rogue process" | 9/3 Fede: "i dont undertadn why there are 2 engines"; one engine merged the same day |
| Contact channel | 4/21 plan led with voice | 9/28: text first, no opening call; 10/11 Fede: "isn't this a text experience? Primary?" |
| Who is bad enough to hold | 5/21 and 7/23: two months owed | Jay 10/7: hold when the balance is above zero; Sean 9/30 pitched 60 days |
| Reminder cadence | Fede 8/31: "reminder 3 times like we do today with leases. business days only. once per day max." | The levels page says the cadence doc and the code disagree (48h/5d vs 24h/7d). The ruling is dated 8/31 on one page and 9/3 on another. |
| Quiet wrap-up | 7/17: wrap up quietly | 8/13 Fede: never give up on a tenant; the audit calls the two "a straight contradiction" |
| Legal gate | 6/22: "Do NOT add a legal/eviction gate" | 7/20: "Legal stuff needs an ADR first — very delicate." |
| Stated vs built | 6/8 Fede: "I'm gonna turn on the autonomous renewal"; 7/23 "its already on" | ADR-0066 (6/22): "Camellia runs holdover-only (autonomousRenewalEnabled off), so no autonomous renewal offers have ever gone to a real tenant" |
| Module order | 9/4 maintenance, leasing, renewals; 9/18 leasing, maintenance, renewals last | 9/23 renewals before maintenance (customer's phone contract). 10/1: renewals first. |
| Asking staff | Camellia retro 9/4: do not ask staff who will not answer | Western Slope reviewers must answer each month |
Camellia (single-community owner, live since spring)
| Date | Who | Said |
|---|---|---|
| 2026-07-08 | Gera to Joanna | "Would you want it, Joanna, to go to you, where maybe you send it, um, or you confirm it, and then it would send, or do you want us to just send it on your behalf?" (no answer recorded) |
| 2026-07-16 | Joanna | "if they owe, like, 2 months or more, they're getting sent a 10-day, and they're not being offered a renewal" |
| 2026-07-16 | Kenya | "I think we were saying to countersign within 72 hours" |
| 2026-08-13 | Spanish-speaking tenants (relayed) | "who is Clara" |
| 2026-08-20 | Kenya | "we could still potentially keep her and just have her month to month for September, and then she renews in October" |
| 2026-09-17 | Joanna | "I don't think we should offer them right now, anyway." |
| 2026-09-17 | Kenya | asks for a 'transferred' outcome "so it shows that they stayed" |
Western Slope (centralized manager, planned Supervised go-live 10/14, first set for 10/12)
| Date | Who | Said |
|---|---|---|
| 2026-09-30 | Jay | "there's certain tenants that have bad payment history that we just want to go month-to-month with, we don't want to lock them in." |
| 2026-09-30 | Jay | "We need to schedule a move out in that folio" (wants non-renewals to start the next steps automatically) |
| 2026-10-07 | Jay | "I want to renew people at zero" (balance zero) |
| 2026-10-07 | Jay | "If we haven't, you know, redirected her or told her no, then she goes ahead." (the heads-up ask) |
| 2026-10-07 | Jay | "Clara will build an agenda, we'll review the items she has escalated in our, you know, our weekly or monthly renewal meeting" |
| 2026-10-07 | Jay | "building the templates is out of scope"; Lincoln and Courtyard stay manual; questions go to "Kat, and she'll escalate to me if she needs to." |
| 2026-10-07 | Jay | "It used to be $100, and now it's $150." (month-to-month fee) |
Situs Group (8/25, not live): "How do we hone in on the unknown still, where, like, they haven't made a decision?" and a fear of a "fat finger" rent error, answered with human-in-the-loop first.
Read-only pass over production: renewal records, leases, conversations and the email log in the production database, plus the 16 Temporal workflow histories that still exist. Tenants appear as initials plus unit, staff as initials. This extends the 09-28 doc sections "What the data says" and "Camellia month-to-month rollover" and does not repeat them. Evidence ids are in the index at the end.
TL;DR
---
Daily scan, 8:30 am Denver, 7 days a week
└─► prepare the offer in AppFolio ──(fails)──► hand-off to the office
└─► letter text with PDF ─► call about 1 minute later
└─► reminder on day 2 ─► reminder on day 9
└─► nudge at lease end −60 (only runs that reach it after 10/1)
└─► nudge at −30 ─► nudge at −15 ─► lease end
Tenant says "yes" ─► 14-day wait for a signature ─► office email "said yes, nothing signed"
Tenant silent ─► workflow exits quietly ─► daily scan rolls the lease to month-to-month
| Step | Design | What happened at Camellia |
|---|---|---|
| Open | Daily scan | Until late June, staff opened rounds by hand, mostly on weekday afternoons. Since then the scan opens them in bursts (for example 7/2, 8/2, 9/1, 9/3). Lead time ranged from 8 to 119 days before lease end. |
| Prepare offer | A failure goes to the office | 27 failure hand-offs. 7 rounds never got an offer. |
| Offer text | Sent inside send hours | 51 offer texts to 40 tenants, 11 of them duplicates. None at night. |
| Call | About 1 minute after the text | 50 calls. 7 reached the tenant. |
| Reminders | Day 2 and day 9 | 69 sent, 38 of them on a weekend. |
| Nudges | −30 and −15 days (−60 is new) | 18 sent: 14 at 6 pm, 4 at 8:30 am. |
| "Yes" | 14-day wait, then an office email | Nothing goes to the tenant during the wait. Two such emails so far (P.D. 607, S.B. 215). |
| Silence | Exit, then month-to-month | 4 rollovers: 3 on 9/5 and 1 on 9/30. |
| Engine | Every live round has been a Temporal workflow since 9/3 | 16 histories readable: 11 running, 4 completed, 1 failed. |
The window is 58 renewal rounds whose first touch fell between 4/22 and 9/18 (lease ends 4/30 to 12/31). State as of 10/12.
| Step | Rounds | Who |
|---|---|---|
| Renewal rounds | 58 | One round = one tenant and one lease end |
| Offer never created | 7 | J.B. 306, G.S. 204, L.F. 416, I.G. 515, M.S. 220, C.H. 317, B.S. 409 |
| Clara stood down because the office had it | 2 | J.S. 404, S.D. 417 |
| Contacted | 49 | 40 by text (most also got a call), 9 by call only (April and May) |
| Engaged | 15 | 7 in writing, 7 on a live call, 1 callback |
| Renewed | 24 | 17 after Clara's outreach, 7 done by the office in AppFolio |
| Gave notice | 16 | |
| Moved to another unit | 4 | |
| Month-to-month | 2 | L.G. 522, G.S. 204 |
| Still open | 10 | Lease ends 10/31 to 12/31 |
| Stuck / unknown | 1 / 1 | B.S. 409 / T.B. 517 |
How replies were counted. "Replied" means at least one written message from the tenant in the renewal thread after the first offer. That is a text, or an email to the manager that landed in Clara's thread (P.D. 607). "Engaged" also includes a live call where the tenant talked about the renewal, and a callback about it. Screeners, voicemail and household members do not count.
Renewal rate. Across all rounds, 24 of 44 decided rounds renewed (55%); "decided" means renewed, gave notice or moved units. On the 09-28 doc's June 25 to December 31 cohort, the rate is now 14 of 36 (39%); the doc had 9 of 32 (28%).
Changes since the 09-28 doc. The doc's list of leases was not stored, so the "today" column below is a rebuild: 50 leases versus the doc's 52.
| 09-28 doc | Today | |
|---|---|---|
| Renewed | 9 | 14 |
| Gave notice | 19 | 17 |
| Moved units | 4 | 5 |
| Month-to-month | n/a | 2 |
| Still deciding | 15 | 10 |
| Stuck, no offer | 3 | 1 |
| Never contacted | 2 | 0 (B.S. 409 is counted as stuck) |
| Unknown | n/a | 1 |
| What changed | Detail |
|---|---|
| Signed | L.L. 410 and D.S. 505 signed 10/2 and were countersigned 10/6. C.D. 512 signed 10/2. Its workflow still waits for the countersignature, though AppFolio already shows the new end date (10/31/2027). *Inferred:* when the 14-day wait ends on 10/16, the office may be asked to chase a lease that is already done. S.B. 215's lease now ends 10/31/2027; the signing date is unknown. |
| Sync | Closed 8 stale records on its own: 7 on 10/2 and I.G. 515 on 10/6. Renewed: P.D. 607, B.G. 608, S.D. 417. Left their unit: J.B. 306 and L.F. 416 (moved units), M.S. 220 and C.H. 317 (gave notice). |
| New | E.L. 302 gave notice (10/1). G.S. 204 rolled to month-to-month (9/30). |
| Broke | B.S. 622's workflow crashed 10/1 because the lease had been archived. |
| Quiet | No new rounds since 9/18. The 5 leases ending in January 2027 enter about 11/2. |
Engagement is low, as Fede thought. But more renewals are lost after a tenant answers than by tenants staying silent.
| Measure | Value |
|---|---|
| Wrote back, of 40 texted | 7 (18%) |
| Any engagement, of 49 contacted | 15 (31%) |
| Calls since June / decisions from them | 34 / 0 |
| Silent tenants who renewed anyway | 12 of 34 (9 on Clara's offer) |
| Engaged tenants Clara closed cleanly | 6 of 15 (G.K. 509, J.B. 516, T.H. 104, S.R. 601, S.K. 603, A.S. 503) |
| ...closed with the office's help | 1 of 15 (E.N. 210) |
| ...dropped by Clara or the hand-off | 6 of 15 (S.B. 215, M.G. 504, P.D. 607, V.G. 614, C.Z. 120, E.A. 114) |
| ...hostile or hung up | 2 of 15 (D.F. 105, R.D. 308) |
Replies follow a touch. 5 of the 7 written replies came within 20 hours of one: the letter (S.K. 603, 40 min), reminder 1 (A.S. 503, 0.8 h), reminder 2 (S.B. 215, 1.6 h; E.N. 210, 19.5 h), and the 30-day nudge (V.G. 614, 3 min). Weekend texts are not the problem: 2 replies came on a Saturday.
| When the call went out | Calls | Reached the tenant | Decisions |
|---|---|---|---|
| Weekday, 12 to 5 pm | 19 | 5 | 4 |
| Weekday, before noon | 21 | 1 | 0 |
| Weekend morning | 5 | 1 | 0 |
| Evening | 5 | 0 | 0 |
*Inference:* most of the afternoon calls were in April and May. Staff had started those rounds by hand, 8 to 54 days before lease end. Time of day, lead time and staff choosing the tenant are tangled together, and this data cannot separate them.
| # | Failure | Count | Verbatim example | Tag |
|---|---|---|---|---|
| 1 | Empty or failed replies | 0 empty. 3 threads where Clara admitted a tool failure (E.N. 210, E.A. 114, T.H. 104). 2 replies swapped by the safety check. | E.A. 114 on a call: "I wasn't able to flag that just now, so I'd suggest reaching out to the leasing office directly". T.H. 104 said thank you twice ("The management here is truly world class"). Each time the safety check blocked Clara's reply and swapped in "I'm looping in your property manager… They'll follow up shortly." No one was looped in. | bug |
| 2 | A yes with no follow-up | 3 (S.B. 215, M.G. 504, P.D. 607) | M.G.: "Yes thank you" to the 6-month term. Clara: "You'll get a recap text with the updated details and your signing link." It never came: AppFolio blocked the term change ("Out for Signing"). The 8/15 nudge still pitched the 12-month. The lease rolled to month-to-month 9/1. She later signed a 6-month lease through the office. S.B. got "You're all set", then 14 days of silence. The office email then said "the renewal window has run out" with 35 days left. | bug + product gap |
| 3 | A no without notice guidance | 0 | S.K. 603's no got the portal steps (row 2 of "What works"). | works |
| 4a | Escalations sent but not answered in the thread | 3 escalations, 2 tenants | P.D. 607 asked for $1,000 (8/3), then chased (8/6). Clara replied: "I've sent them a second nudge flagging the August 9 deadline." The thread never got an answer; the office settled it in AppFolio later. M.G. 504's 8/21 request for "a physical copy" has no recorded action. E.N. 210's escalation was answered the same day, and V.G. 614's was handled in AppFolio. | product gap |
| 4b | Things that never reached the office | 7 | E.A. 114 needs Spanish. M.R. 303's household asked for mail. B.G. 608's new number. C.Z. 120's dropped callback. D.F. 105 thinks it is a scam. T.H. 104's fake loop-in. V.G. 614's "I've taken you off the list". | bug |
| 5 | Texts after the tenant answered | 6 tenants, plus 1 late read | A.S. 503: "I signed my renewal yesterday! Did I miss something?" V.G. 614 had said she signed a paper 6-month lease. The 15-day nudge went anyway: "Please do not text me again". E.S. 518 and R.R. 224 had notices on file since 7/7, yet got this on 7/31: "You can still renew at $1,750/mo". P.D. 607 and M.G. 504 also got nudges after answering. B.M. 420 is a different bug, a late read: her notice was dated 8/1 in AppFolio, but Clara saw it only on 9/11, so the nudge and the month-to-month notice went out anyway. | bug |
| 6 | Wrong person | 3 | B.G. 608's former roommate: "This phone number is no longer associated with Apartment 608… more than happy to share her contact info". Clara: "I'm not able to accept contact info for another resident through this channel". Staff had asked for that number 2 hours earlier. A nudge still went to that phone 7/28. M.R. 303's household member: "just send me a piece of mail" was refused. | product gap |
| 7 | Holds that expired silently | 0 | No renewal holds exist at Camellia, and supervised review is not used. | n/a |
| 8 | AppFolio before or instead of Clara | 1 call; 13 office renewals | S.M. 616 called about an AppFolio renewal email (6/8). Clara: "I don't see an active renewal on file for you right now". The transfer that followed ended in "Hello? Hello." Within Clara's rounds, 7 renewals were done by the office in AppFolio. 6 more office renewals never had a Clara round. *Inferred:* AppFolio sends its own email for offers the office creates, and Clara cannot see them. | product gap |
| 9 | Month-to-month drift | 4 rollovers | New since the doc: G.S. 204 rolled on 9/30, and its offer never existed. 8 active leases now have no end date. P.C. 118 and P.W. 111 still say month-to-month although both renewed. | bug |
| 10 | Duplicate offers | 11 extra texts, 6 rounds | On 5/26, P.C. 118 and B.G. 608 each got 3 letters plus 1 offer text within 90 minutes. D.M. 620 had the full sequence from 7/13, then got a new letter and reminder again at the 9/3 cutover. | bug |
| 11 | Timing | see detail | Calls went out at 8:30 am, including Sunday 8/2: "Shut up, scammer." (D.F. 105). Others: Sunday 7:44 pm (3 calls), Friday 9:23 pm. A.P. 212 got the offer 14 days out; the 12/31 group got it 119 days out. Silent gaps: leases ending 11/30 hear nothing from 9/12 to 10/31 (49 days), 12/31 leases from 9/12 to 11/30 (79 days). Office "ready for your signature" emails went out Friday at 8:21 pm. | bug |
| 12 | Replies on another channel | 4 | C.Z. 120 called back a minute after a Sunday voicemail: "I think you just sent me a voicemail today for, um, our renewal". The transfer dropped: "Hello? Hello?" P.D. 607 and V.G. 614 emailed the manager, and those emails landed in Clara's thread. T.H. 104 texted into the call thread at 3:37 am. | product gap |
Beyond the checklist
| Failure | Detail | Tag |
|---|---|---|
| Spanish-speaking households | 5 households show Spanish signals. E.A. 114 asked for Spanish. B.M. 420 called the line in Spanish. R.P. 201 answered in Spanish. Y.C. 610's call screener and L.G. 522's voicemail greeting are in Spanish. Every renewal text and call was in English. On the renewal call Clara says "I'm only set up for English at the moment", yet the inbound line switched to Spanish for B.M. 420 on 6/3. None of the 5 has renewed: 2 gave notice, 1 rolled to month-to-month, 2 are open. The language field is blank on 110 of 121 records. | product gap |
| Offer never created | G.S. 204's offer failed 7/13 because a signer had no email. The 09-28 doc covers the 9/15 nudge for that missing offer. New since then: the clear "add an email" notice reached the office only on 9/16, and the lease rolled to month-to-month on 9/30. A 7/13 hand-off may also have gone out, but the email log starts 9/12. L.F. 416 had 10 records in a July retry loop. B.S. 409 has been stuck since 9/3, with the lease ending 11/30. | bug |
| Wrong copy or state | T.B. 517's offer: "your lease is coming up on your lease end date". B.G. 608's nudge said "about two weeks away" with 3 days left. S.B. 215's text "yes" was recorded as a voice intent. P.D. 607's record flipped to "Tenant signed" on 7/31, but P.D. had not signed. The 8/14 office email said "agreed verbally", but P.D. had made a counter-offer that was never answered. | bug |
| Crash | B.S. 622's workflow failed 10/1 at the 30-day nudge: "Lease … not found in property". The lease had been archived and another tenant moved in 9/1. | bug |
| A renewal call reached a non-tenant | On 6/26 a renewal call reached a Spanish-speaking apartment hunter. Clara's leasing side booked a same-day tour, while the renewal voicemail line ("Sorry I missed you") also played. That person moved into unit 201 on 7/1. No renewal round matches this call. | bug (cause unknown) |
| What the office received | Count |
|---|---|
| "Completed" notices (S.J. 411, D.F. 203, M.A. 511, E.N. 210, J.L. 401) | 5 |
| "Agreed verbally, nothing signed" (P.D. 607, S.B. 215) | 2 |
| "Rolled to month-to-month" (M.G. 504, L.G. 522, B.M. 420, G.S. 204) | 4 |
| "Blocked, a signer is missing an email" (G.S. 204) | 1 |
| Offer-preparation failure hand-offs | 27 |
| Renewal escalations from tenant threads (E.N. 210, P.D. 607 ×2, M.G. 504, V.G. 614) | 5 |
| Rank | Change | Evidence | Tag |
|---|---|---|---|
| 1 | Stop every reminder and nudge the moment the tenant answers, signs, says they signed on paper, gives notice or says stop. No "you can still renew" text after a notice. Read AppFolio notices within a day. | 6 tenants (row 5); B.M. 420's notice was seen 41 days late | bug (fix, no switch) |
| 2 | Keep every promise made in the thread: the recap text and signing link, the term rebuild, or a same-day note to the office when AppFolio blocks it. | M.G. 504, S.B. 215 | bug (fix, no switch) |
| 3 | After a "yes", chase twice during the 14-day wait instead of going silent. | S.B. 215, P.D. 607 | product gap (improves a live flow) |
| 4 | Every hand-off reaches the office, even when the tool fails. Never claim "looping in your property manager" without doing it. Tell the office about a blocked offer the same day, in plain words. | E.A. 114, T.H. 104, G.S. 204, B.S. 409 | bug (fix, no switch) |
| 5 | Spanish offer, reminders and renewal call. Set the language from the inbound line or a Spanish voicemail greeting. | 5 households, 0 renewals | product gap |
| 6 | Drop the 8:30 am opening call, as the 09-28 doc recommends. If voice stays, one weekday-afternoon call about 30 days out, for silent tenants only. | 34 calls since June, 0 decisions; afternoon 4 of 19 vs morning 0 of 26 | product gap |
| 7 | Fill the silent gap: give running workflows the 60-day touch. | Nov/Dec leases hear nothing for 49 to 79 days | bug (fix, no switch) |
| 8 | Clean up the records: no duplicate letters on retry or cutover; guard against the missing-date placeholder; exit quietly when a lease is archived; record the real channel; a counter-offer is not a "signature"; correct "days left" copy. | rows 10 and 11, crash, wrong-copy row | bug (fix, no switch) |
| 9 | Accept a new number or "mail it to me" from a household member and pass it to the office. | B.G. 608, M.R. 303 | product gap |
| 10 | A counter-offer loop with a deadline set before AppFolio's signing deadline. | P.D. 607. Every offer equals current rent, and 26 of 51 priced offers sit above market (median +$150). | product gap |
| 11 | Callbacks about a renewal are handled on the line, not transferred into silence. | C.Z. 120, S.M. 616 | product gap |
The 09-28 doc already recommends email as a second offer channel. The new data supports it: 2 of the 7 written repliers emailed the manager, and 18 of 121 records have no email on file.
---
| Who | Ids |
|---|---|
| G.K. 509 / J.B. 516 / S.R. 601 / T.H. 104 calls | conv_voice_faa909e2-ddb8-4038-91a7-f3aa3f16116e, conv_voice_8ff1882f-ce2d-479e-b56a-4d0162b2a97e, conv_voice_ebd0e13d-63b8-4432-9341-2aab10b8b768, conv_voice_6a15e577-975c-4e70-aeba-1f8c252603ad (also T.H.'s 5/27 blocked replies); saga_4c8d1956, saga_25395c2a, saga_a35c4cef, saga_6f3a772f |
| S.K. 603 | conv-renewal-tenant_61656d50-f15e-4e2a-ab34-05295e33c562-1782323715356; saga_911286b7, saga_d92aeeeb |
| E.N. 210 | conv-renewal-17736259534620024-1783711349011; saga_8f5eeae8 |
| S.B. 215 | conv-renewal-17736259534620027-saga_cba1063a-a014-4959-96b3-1a5a28374125; saga_cba1063a; workflow renewal-lease_d6d15602-ba2e-4e3e-abfb-2c8a01f6d8b9-2026-10-31 |
| M.G. 504 | conv-renewal-17736259534620070-1782258013197; saga_fe7b4e8f (CHANGE_TERM_BLOCKED 8/5) |
| P.D. 607 | conv-renewal-17736259534620090-1783711828815; saga_fba0927a |
| V.G. 614 | conv-renewal-17736259534620095-1782258178956; saga_7a698406, saga_47f350e4 |
| A.S. 503 | conv-renewal-17736259534620069-1783002874143; saga_e0116702 |
| E.S. 518 / R.R. 224 | conv-renewal-17736259534620081-1781302987376, saga_e015ff8d / conv-renewal-17736259534620033-holdover-lease_50cd376f-3f1e-46d0-98ae-9301b2f46d21, saga_bbae8a97 |
| B.G. 608 | conv-renewal-17736259534620091-1779833522875 (and …1779828358269, …1779830122293, …1779833521958 for the duplicates); saga_7b75fad0 |
| M.R. 303 | conv_voice_f6e74c6b-84ce-40c3-b041-7fbf25f4a66d; saga_0e76cffa; workflow renewal-lease_de05329b-2b3a-4f64-883d-cf13a3ad3364-2026-12-31 |
| E.A. 114 | conv_voice_fc153c0b-bce6-47f9-9d86-af6c032e6eea; saga_8454bf4d; workflow renewal-lease_400b86d9-3bf0-4818-b8a5-3126c0ed9b55-2026-11-30 |
| D.F. 105 | conv_voice_d2c50186-050a-40f4-8722-6d29d24bb68a; saga_5e5c4fec; workflow renewal-lease_626f847b-147b-4f8b-a31d-a926b46f5f98-2026-10-31 |
| C.Z. 120 | conv_voice_783a7a9a-d18d-4dc4-9ba0-67318ad65dd3 (voicemail), conv_voice_ade27c7d-b195-481b-a2df-780f56ec7980 (callback) |
| S.M. 616 | conv_voice_5d7cb67d-3661-435d-9e45-38fcd966bf6d |
| G.S. 204 | conv-renewal-17736259534620021-saga_33866181-674f-44b0-8855-9c645c51cc5b; saga_33866181 |
| L.F. 416 | 10 records: saga_eadb0a13 … saga_e17df2a9 |
| B.S. 409 | saga_67326c3c; workflow renewal-lease_a2d3f5f8-e7d5-433e-895f-7035603bdc84-2026-11-30 |
| B.S. 622 (crash) | saga_533f66e2; workflow renewal-lease_3505f7d6-a674-4ab5-90c3-b403a2062e51-2026-10-31 |
| T.B. 517 | conv-renewal-17736259534620080-1784127808366; saga_b03479b6 |
| D.M. 620 | conv-renewal-17736259534620100-1783953223007 (7/13), conv-renewal-17736259534620100-saga_8f533020-… (9/3) |
| C.D. 512 / L.L. 410 / D.S. 505 | workflows renewal-lease_98be4668-9559-4a4a-a8c9-f4b98666517f-2026-10-31 (running), renewal-lease_4871ca18-39a2-4d93-bd97-02f59be866c6-2026-11-30, renewal-lease_bbbc3347-f422-4199-80a8-3570d8e13609-2026-11-30 |
| R.P. 201 call | conv_voice_94e6e07b-2acf-4a35-977f-de171590d271 |
| D.B. 609 / C.H. 618 screeners | conv_voice_c3ce06c9-636f-4826-9a59-8a9d340b9017 ("you've reached Cloaked AI"), conv_voice_9f123e5c-b045-48c0-ab88-54557de124c1 ("Please say who you are") |
Every renewal decision since June, read from the raw transcripts of team and customer calls (#transcripts, per-speaker text, not the recaps), the bridge channel, and Fede's own words in Claude sessions. Quotes are verbatim. "Customer stated" rows are the customer's policy, not ours. 281 meeting threads read, about 100 with renewal talk; 427 quotes checked; 42 decisions below.
Still in force. Never below current rent (7/16). AppFolio is the truth (7/28). No outbound to a delinquent tenant unless the customer approves the list (8/31, 10/14). One renewal engine (9/3) and the replay lab (9/4). Camellia stays fully autonomous. New customers get texts, not calls (10/5). Western Slope: Supervised, messages only, their team does paperwork, rent flat (10/7 to 10/12). Review offers On by default (10/14).
Gap. The 9/19 "customers never review, review mode TEMPORARY" ruling has no raw transcript, channel or session source (checked 2026-10-14 against 281 transcripts); the word "temporary" comes from the 8/30 Camellia rollout safeguard. It was superseded on 10/8 when Gera and Fede agreed customers can review.
| Date | Source | Who | Decision | Quote | Superseded by |
|---|---|---|---|---|---|
| 6/03 | Standup/call transcript | Sean, Fede | Camellia: a tenant who does not sign goes month-to-month; Clara changes it in AppFolio. | "then Clara will go in and change it to month-to-month in AppFolio." (Sean) | Still in force; Western Slope said the same on 10/7. |
| 6/08 | Standup/call transcript | Fede | Camellia: renewals go fully autonomous, no approvals. | "after this call, I'm gonna turn on the autonomous renewal, so I don't have to approve them anymore." | Still in force at Camellia (Fede 10/6: "Camellia should be fully autonomous"). New customers start Supervised instead (10/7 on). |
| 6/08 | Standup/call transcript | Fede | Camellia: a tenant with more than two late payments is flagged for human review. | "Someone has more than two late payments." / "Yeah, it's flagged for human review, yeah." | Refined 7/16 and 8/4 (balance rules). |
| 7/16 | Standup/call transcript | Fede | Camellia: fully automatic; Clara calls and texts the letter; month-to-month costs $100 more. | "It's fully automatic now. Like, I'm not approving anything." / "And that has a $100 premium." | Calls dropped for new customers 10/5. Western Slope fee is its own ($150, 10/7). |
| 7/16 | Standup/call transcript | Camellia staff (customer stated) | Camellia: a tenant who owes 2 or more months gets no renewal until caught up. | "if they owe, like, 2 months or more, they're getting sent a 10-day, and they're not being offered a renewal" | Tightened 8/31. |
| 7/16 | Standup/call transcript | Sean | Never offer less than the current rent. | "the rule is we never offered less than what they're already paying." | Still in force (7/23). |
| 7/23 | Standup/call transcript | Sean | No step-downs; renew at the existing rate or higher. | "on renewals, we're not stepping people down. They renew at their existing rate." | Still in force. |
| 7/28 | Standup/call transcript | Fede | AppFolio (the PMS) is always the source of truth. | "the BMS data is always a source of truth." | Still in force. |
| 8/04 | Standup/call transcript | Sean | A balance older than 60 days holds the renewal. | "If they have over a 60-day balance, then it gets flat, then it gets held." | Tightened 8/31. |
| 8/06 | Standup/call transcript | Camellia manager (customer stated) | Camellia: a delinquent tenant gets a renewal only after paying in full. | "as long as he pays everything, then we'll send him a renewal." | Became the 8/31 rule. |
| 8/31 | Claude session a566db0c, 17:51-17:57Z | Fede | No renewal outbound to a delinquent tenant; a balance over the policy blocks it whatever the eviction status. | "this tenant is exxtremely delinquent why did we send that" / "regardless of evicion status the outstanding balance is over the renewal policy right" | In force. 10/14: once the customer approves the monthly list, it goes to everyone on it. |
| 8/31 | Claude session a566db0c, 18:29Z | Fede | Month-to-month holdover belongs inside the renewal workflow, not a separate one. | "i originally wnated the holdover to be attached to the renewal workflow not standalone" | Folded into Option B (9/3). |
| 9/03 | Claude session 28bc997e, 15:04-17:14Z | Fede | Option B: one renewal engine, one owner; delete the second one. | "i dont undertadn why there are 2 engines" / "why do we need another engine vs fix wha twe had?" / picked "B — one owner (recommended)" / "i want to never worry about this again" | Still in force. |
| 9/03 | Claude session 28bc997e, 14:36Z | Fede | Timeouts and system errors alert engineering, never the property team. | "timeout issues shuld not go to the property team, it should be an alert to engineering" | Still in force. |
| 9/04 | Claude session 28bc997e, 20:28Z | Fede | Renewals lab: understand each bug, find why the old harness missed it, replay every renewal conversation since launch. | "phase one here is to be able to cnissitently repdocue in a lab environment. this will include replaying eveyr single renewal conversation / issues weve had since lanuch" | Still in force (now the testing ladder, 10/9). |
| 9/04 | Standup/call transcript | Sean | Western Slope order: maintenance, leasing, then renewals. | "And then, I think, renewals after that." | 9/9. |
| 9/09 | Standup/call transcript | Western Slope staff (customer stated) | Western Slope order: leasing, then renewals, then maintenance. | "if we're going to focus leasing and then renewals and then maintenance, I think that's fine." | Confirmed 9/23. |
| 9/19 | no raw source found | (cited as Fede) | "Customers never review; review mode is TEMPORARY." Section J of this page cites it; no transcript, channel post or session line from 9/16-9/22 says it. The word TEMPORARY traces to the 8/30 Camellia bake gate. | none found | Overturned 10/8: customers can review. |
| 9/23 | Standup/call transcript | Fede | Western Slope: renewals come next after leasing. | "I think renewals make sense." | Still in force. |
| 9/30 | Standup/call transcript | Fede, Gera | First week Supervised: PropFlow reviews each renewal in Slack, within one to two hours. | "first week it's supervised" / "we review it on Slack, click approve, send it." (Fede); "within the hour to two hours" (Gera) | 10/8-10/9: the customer reviews too, by email. |
| 10/05 | Standup/call transcript | Fede | New customer: no renewal phone calls, texts instead. | "I'm not even gonna try to call people for renewals, because nobody picks up" | Still in force (10/12: text on the cadence). |
| 10/05 | #engineering-bridge (bot relay of Fede) | Fede | Western Slope renewals wait for their written policy. | "Still waiting for the client to tell us the policy" | 10/7 call gave it. |
| 10/07 | Standup/call transcript | Western Slope staff (customer stated) | Western Slope policy: 90-day start, 12-month default, renew tenants at a zero balance. | "Clara opens each renewal 90 days before lease ends, yes. We offer a 12-month" / "I want to renew people at zero." | Still in force. |
| 10/07 | Standup/call transcript | Sean, Western Slope staff | Western Slope: no reply converts to month-to-month; the fee is in their lease ($150, was $100). | "If they don't reply by the expiration date, it just converts to month-to-month." (Sean) | Still in force. |
| 10/07 | Standup/call transcript | Sean | Western Slope rent: bring renewals up to market. | "renewal rent, we would just bring it up to market" | Same day: flat or $25; 10/12: flat. |
| 10/07 | Standup/call transcript | Fede, Gera (internal call) | Start Western Slope simple and Supervised. | "Not the fully autonomous, fully fancy version." (Fede); "we definitely would want to have some sort of supervised mode right now." (Gera) | Still in force. |
| 10/07 | Standup/call transcript | Fede | Step one sends only the messages, not the contract. | "Step one could be not even send the contract, just send the communication." | Still in force. |
| 10/07 | Standup/call transcript | Fede | One list to the customer: "here are the renewals, review them." | "we're gonna renew these people, let us know otherwise." / "these are the renewals, review them." | Built as the monthly list (10/9). |
| 10/07 | Standup/call transcript | Fede | Western Slope rent: flat or +$25. | "And either call it flat or 25." | 10/12: flat. |
| 10/08 | Standup/call transcript | Fede | Messages and paperwork are separate; the customer team does paperwork until ready to graduate. | "we can just do the communications, and then your team does the paperwork, and once you're comfortable, we graduate you to paperwork" | Still in force. |
| 10/08 | Standup/call transcript | Gera, Fede | Supervised approvals can go to the customer; Supervised is temporary. | "it could also go to the client" (Gera); "start the supervised mode as soon as possible ... and then eventually we'll not have that." (Fede) | Overturns the 9/19 citation. |
| 10/08 | Standup/call transcript | Sean | Assume +$25 for January; go live Monday. | "we'll just assume a 25 increase for January" / "Monday, we're gonna go live with renewals." | 10/12: flat, Wednesday. |
| 10/08 | #engineering-bridge (bot relay of Fede) | Fede | New setting "who sends the paperwork", default Clara. | "'who sends the renewal paperwork: Clara in AppFolio / your team', default Clara, dark." | 10/12: default is the team. |
| 10/08 | Claude session f86757cf, 18:59Z | Fede | Walk Western Slope slowly toward full autonomy, starting Supervised. | "the customer isn't ready yet for fully autonomous sending out the leases" | Still in force. |
| 10/09 | Standup/call transcript | Fede | Western Slope: Supervised, flat or +$25, the customer reviews by email, approval sends only the messages. | "They will get an email where they can review" / "Approving sends only the communications and not the paperwork" | Rent: 10/12 flat. |
| 10/09 | #engineering-bridge (bot relay of Fede) | Fede | One list email on the 1st of each month; no setting for it. | "one batch email on the 1st of each month" / "No, I don't, I don't think we want a setting for this." (session 1fcfe5de, 18:54Z) | 10/13: list review is its own setting. |
| 10/12 | Standup/call transcript | Fede, Gera | Levels: messages and reminder texts first, then the customer's own policies, then Clara sends the contract. | "approve them, and then we'll just text people" ... "the last level is Clara sends a contract for you" | Still in force (this page). |
| 10/12 | Standup/call transcript | Fede | Western Slope go-live moves to Wednesday 10/14. | "One more day of testing. But by our meeting on Wednesday." | Done 10/14. |
| 10/12 | Claude session 1fcfe5de, 21:55-22:25Z | Fede | Paperwork defaults to the customer team; reviewers live in the customer UI; Western Slope rent flat; only affordable-housing buildings skip renewals. | "if it's not set like you should default to the team" / "flat" / "yes they are affordable housing" | Still in force. |
| 10/13 | Claude session 1fcfe5de, 19:36Z | Fede | Supervised (PropFlow checks outbound) is separate from the customer setting "review before it goes out". | "the supervise switch has nothing to do with that's just us reviewing the outbounds. But the reviewing the model list, that's a feature in itself." | Still in force. |
| 10/14 | Claude session 1fcfe5de, 16:35-18:09Z | Fede | Review offers is On by default; the list shows the next 90 days (a setting); an approved list goes to everyone on it. | "review offers should be on by default" / answered "yes" to "Yes, everyone on the list: they reviewed every row" | Still in force. |
| 10/14 | Standup/call transcript | Fede | Western Slope renewals are ready to turn on in Supervised. | "Renewals is ready to turn on in supervised mode" | Turn-on is Fede's press. |