Two good email standards exist. Most senders don't use them.
2026-10-14 · Proposed — D1 decided A (Fede, 2026-10-14); D2 pending · first audit + independent Fable re-audit, code on main 17a066e59a, 22 days of send logs · internal
TL;DR The two standards Double audit Production Consistency map Delete list Decisions Plan
Two standards, no new templates. Team email = a plain note from Clara. Outside email = the prospect reply email.
The problem is consistency. 6 sender files use the team note and 3 use the prospect email; the rest spread over 9 other looks and 6 ways to send.
Double audit. An independent Fable re-audit checked the first audit's 18 claims: 4 held, 10 were wrong, 4 unproven or partly right.
False alarm. The missing-email-key incident was not real: production has never been missing the key (checked 2026-10-14 night).
Next. Nothing built tonight. After this week's renewals flip is proven: deletions, one helper per standard, small moves, then a build check.
| Standard 1: team | Standard 2: outside | |
|---|---|---|
| Who gets it | The customer's office staff, reviewers, our own team | Tenants, prospects, applicants, vendors, owners |
| Looks like | A plain note from a coworker, small Propflow logo at the bottom | The white card prospects already get (Fede, 2026-10-14: "I like the one we send to prospects already for external") |
| Signed | "Clara" | "Clara, Leasing Assistant" + property |
| Helper on main | emailPlainNoteLayout (agents/clara/lib/messaging/transports/stripe-base.ts:259) + CLARA_SIGN_OFF | buildClaraReplyHtml (clara-reply-template.ts:338) + buildClaraReplyPlainText (:223) |
| Door | Team-notice door, sendOrHoldTeamNotice (team-notice-send.ts:123) | Property email door, sendPropertyEmail (property-graph-sender.ts) |
| Ruling | Never held under Supervised (Fede, 2026-10-14: "Supervised is meant to be for prospects and tenants"; rule 10, #19625) | Supervised holds Clara's messages to tenants and prospects |
Desktop, 640

Phone, 375

"Tenant said yes", 640

375

"Tenant countered", 640

375

Desktop, 640

Phone, 375 (does not shrink)


| # | Finding on Standard 2 (verified at main) | Where |
|---|---|---|
| 1 | The plain-text version has no signature. AppFolio delivers text only, so prospects at AppFolio-routed properties never see Clara's sign-off. | clara-reply-template.ts:223-240; signature only in HTML :312-316 |
| 2 | The card is a fixed 600 px table with no phone rule; it overflows on a phone. | clara-reply-template.ts:357 |
| 3 | The tour confirmation is a hand copy of the frame, not the helper. | tour-reply-template.ts:120, :229, :267-271 |
An independent Fable re-audit re-checked the first audit against main and the send log. Where they disagree, the re-audit wins.
| # | Claim | Audit 1 said | Fable re-audit | Evidence |
|---|---|---|---|---|
| 1 | Team emails on the note | 26 of 60; 34 off | Unverifiable | No list, no unit. By file: 6 senders use the plain-note shell. |
| 2 | Team emails through the door | 6 of 60 | Confirmed | 6 caller files of sendOrHoldTeamNotice; none of them uses the note shell. (7 since #19612.) |
| 3 | Outside emails on the standard | 0 of 28 | Refuted | Measured against renderExternalEmail, which does not exist. The real standard carries 148 replies + 33 first emails. |
| 4 | Outside count | 28 (TL;DR) and 36 (footnote) | Refuted | Self-contradiction. By file: 14 door callers + 5 direct + account/website mail. |
| 5 | Outside looks | Two branded looks + raw text | Refuted | Four HTML shells reach outside audiences, plus a hero frame, plus 5 text-only senders. |
| 6 | The note is a shared helper used by the list email | Yes | Confirmed | render-batch.ts:224, compose.ts:181. Paragraphs are still hand-built per sender. |
| 7 | The counter note uses the note | Yes, own file | Refuted since changed | No such file at the re-audit snapshot. #19612 added it after: card frame, sent under Supervised. Plain frame is #19701. |
| 8 | coworkerHtml location | stripe-base.ts:259 | Refuted | Line 259 is emailPlainNoteLayout. coworkerHtml is private, preview-only. |
| 9 | Said-yes note uses the card | Yes | Confirmed | renewal-yes-office-notice.ts:37, :110 |
| 10 | Team notes "never held" under Supervised | Never held | Refuted | That is the ruling, not today's door: alsoSupervisedBy holds on Supervised (team-notice-send.ts, #19492). No real company has Renewals Supervised today. |
| 11 | Two doors cover every send | Yes | Refuted | tellStaff (19 files) is a pass-through; 33 files call the transport directly; 4 Graph-direct sends; owner report raw. |
| 12 | Team sends skipping the switch or test guard | 25 | Refuted | Undercount: 28 production sites; company-live-gate.ts:322-328 sends before the test check. |
| 13 | Supervised holds tenant and prospect mail | Yes | Confirmed | With a gap: an approved prospect redraft goes out as text with no frame (bake-gate.ts:2250). |
| 14 | Clara sign-offs on outside mail | 8 | Unverifiable | At least 3 forms found. |
| 15 | Design guide is stale | Last updated 07-09 | Refuted | Updated 10-14 (#19625); step 0 is done. |
| 16 | Checks and helpers listed in Reference | Listed with paths | Split | Implementable, but renderExternalEmail, the staff-email lint rule, check:email-doors and its control do not exist. |
| 17 | Counts pinned to lines | At two commits | Unverifiable | Lines drifted; pin to files. |
| 18 | Inventory complete | Yes | Refuted | The lockbox-missing alert to prospects is in neither audit. |
2,949 send-log rows plus the mail service's counters. AppFolio-routed mail writes no row, so it is missing. Real vs test is a heuristic.
| Email (subject shape) | To | Real | Test | Not delivered (real) | Last real | Look |
|---|---|---|---|---|---|---|
| Clara replies, "Re: …" | prospects, tenants | 148 | 361 | 3 bounced, 1 blocked | 10-14 | Standard 2 |
| "Your inquiry about <home>" | prospects | 33 | 2 | 0 | 10-14 | Standard 2 |
| Follow-ups, "Still looking" | prospects | 29 | 126 | 0 | 10-14 | brand shell |
| Tour next steps | prospects | 8 | 0 | 0 | 10-13 | brand shell |
| Tour confirmed / cancelled | prospects | 6 | 13 | 0 | 10-02 | text only |
| Renewal offer ready | tenants | 5 | 0 | 2 blocked, 1 bounced | 10-12 | hero / card |
| Owner weekly report | owners | 3 | 0 | 0 | — | digest |
| Website thank-you | visitors | 1 | 1 | 0 | 10-07 | marketing |
| Caller and question handoffs | staff | ~250 | ~350 | 11 + 8 blocked | 10-14 | Standard 1 |
| Bake alerts | our engineering | 188 | 0 | 0 | 10-14 | own HTML |
| "Asked us something we could not answer" | staff | 61 | 283 | 4 blocked, 5 lost | 10-14 | Standard 1 |
| Tour confirmed (office copy) | staff | 38 | 473 | 5 lost | 10-14 | card |
| New application / lease ready | staff | 31 | 1 | 0 | 10-04 | card |
| Lead escalated (sender since removed) | our inbox | 28 | 0 | 0 | 09-30 | — |
| Sign-in code | account | 25 | 0 | 0 | 10-14 | card |
| Still waiting on your review | staff | 15 | 0 | 0 | 10-03 | card |
| Emergency / Urgent | our inbox | 14 | 41 | 0 | 10-11 | Standard 1 |
| Team invite | account | 8 | 1 | 0 | 10-06 | card |
| Tour update | staff | 6 | 17 | 0 | 10-06 | card |
| Leads to call this week | staff | 4 | 0 | 0 | 10-14 | digest |
| Renewal completed | staff | 4 | 0 | 2 lost | 10-12 | card |
| Promise-backing notes | staff | 4 | 16 | 0 | 10-04 | Standard 1 / hand-built |
| Sign-in link; internal notes | account, staff | 3 + 3 | 0 | 0 | 10-10 | card |
| Renewal counter ("Action needed") | staff | 2 | 92 | 4 lost | 10-02 | hand-built |
| New lead; guest card not created; month-to-month | staff | 1 each | 23 / 6 / 0 | 5 lost | 09-30 | hand-built / card |
Test only so far: renewal list (26), "Emergency handled" (40), said-yes (4). Outside the code: a daily summary from a job on Fede's Mac (7, now stopped) and a customer website form relay (2).
| What happened | Lost | When |
|---|---|---|
| Failed staff-notice rows blamed on a missing email key: false alarm, written by local scripts, not production | 0 real (42 script rows) | checked 10-14 |
| A nonexistent test mailbox (smoke@) plus 20 bench aliases on the bounce list; test traffic only | 106 drops (log saw 28) | 10-03 to 10-09, stopped |
| Blocks to an undeliverable harness address; test traffic only | 171 | 09-23 to 09-29 |
Every off-standard sender and where it moves. No new helper.
| Sender(s) today | Moves to | Look today | Send path today → after |
|---|---|---|---|
| Renewal completed, holdover, lapse digest, said-yes | Standard 1 | card | door already |
| Key pickup, new-lease draft, move-out mismatch and draft, vendor outcome, PO required, stale dial, action reminders, office tour confirmations, tour update | Standard 1 | card | tellStaff / raw → door |
| Renewal counter (older path), guest-card failure, reply release, owner escalation | Standard 1 | hand-built | tellStaff / raw → door |
| Leads to call this week | Standard 1 | digest | door already |
| Missed call, promise alarm, decision request, emergency, team-notify engine | Standard 1 already | — | raw → door |
| Prospect thread copy to staff | Standard 1 | reply card | property door → door |
Notes behind the teamNotifyEngine switch (on at 2 of 6 companies) | Standard 1 (engine path) | two frames by company | retire the switch |
| Bake alerts (188) | Machine alert: stays plain (D1 A) | own HTML | raw |
| Sign-in code, sign-in link, invite, PMS connect | D2 | card | raw |
| Tour confirmation | Standard 2 | hand copy | property door already |
| Application link, lockbox code, lockbox missing, congrats | Standard 2 | brand shell | property door already |
| Follow-up touches + 4 scheduled outreach jobs | Standard 2 | brand shell | Graph direct → property door |
| Inbound-address reply | Standard 2 already | — | Graph direct → property door |
| Renewal offer | Standard 2 | hero / card / brand shell | property door already |
| Desk-booked tour, property reply, PMS application, vendor completion, PMS email | Standard 2 (HTML + text) | text only | property door already |
| Approved prospect redraft | Standard 2 | empty HTML | property door already |
| Waitlist approved | D2 | card | raw |
| Owner weekly report | Standard 2 (fit of a table report: Fede's call, below) | digest | raw → property door |
| Newsletter and demo thank-yous | D2 | marketing | raw |
| Vendor dispatch, quote, chase, turnover | Standard 2 when vendor mail turns on | brand shell | raw / Graph → property door |
| Layout | From | Brand casing | Sign-off | |
|---|---|---|---|---|
| Sign-in code | card | Clara | PropFlow | none |
| Sign-in link | card | Clara | PropFlow | none |
| Team invite | card | Clara | PropFlow | none |
| Waitlist approved | card | Clara | PropFlow | "— The PropFlow team" |
| PMS connect (IT admin) | card | Clara | PropFlow | none |
| Welcome (never sent) | guide | — | PropFlow | "— The PropFlow team" |
| Newsletter thanks | marketing | Propflow | Propflow | "The Propflow team" |
| Demo thanks | marketing, old "PropFlow.ai" logo | Propflow | mixed | "The Propflow team" |
The logo and brand cheat sheet say "Propflow"; 6 of 8 emails say "PropFlow".
Sign-in code

Sign-in link

Team invite

Waitlist approved

PMS connect

Welcome (never sent)

Newsletter thanks

Demo thanks

| # | What | Why it is dead | Risk |
|---|---|---|---|
| Done 10-14 | "PropFlow AI Agents - Daily Summary" email | A scheduled job on Fede's Mac, not production code; schedule uninstalled on Fede's instruction | — |
| 1 | Welcome email + its guide layout | Only the admin preview uses them | none |
| 2 | Tour-request email | Preview and a dev-only route | none |
| 3 | Renewal accepted / declined staff emails | Tests only | none |
| 4 | Tour reminder email builder | No job imports it; reminders go by text | low |
| 5 | Old manager-escalation builders | Preview and a voice harness only | low |
| 6 | Dev "send test email" route | No auth inside; relies on the production 404 | low-medium |
| — | Gas / urgent subjects, lead-watchdog email | Already removed (#14337, #14029) | — |
Also: owner weekly report into the prospect card? Recommend yes if it fits a phone.
Also: clear smoke@ from the bounce list? Recommend hold: the mailbox does not exist; point the test companies at test@ instead.
No building tonight (Fede). After this week's renewals flip is proven:
Related: #19650 (counter note missing from the renewal thread).
Open item: a customer website form relays "Website contact" leads with our production mail key from outside the codebase; move it to its own key.
| Plain term | Code on main |
|---|---|
| Team note | emailPlainNoteLayout({ preheader, body, logo: 'small-bottom' }) (agents/clara/lib/messaging/transports/stripe-base.ts:259) + CLARA_SIGN_OFF; callers render-batch.ts:224, team-notify/compose.ts:181, decision-request.ts, emergency-alert-notices.ts, missed-call-note.ts, promise-alarm-note.ts |
| Prospect email | buildClaraReplyHtml / buildClaraReplyPlainText (agents/clara/lib/email/clara-reply-template.ts:338 / :223); callers send-clara-prospect-email.ts, clara-guest-card-first-email-send.ts, lambda/inbound-processor/handler.ts |
| Card / marketing / guide | emailCardLayout (stripe-base.ts:167), emailMarketingLayout (:318), emailGuideLayout (:391) |
| Team-notice door | sendOrHoldTeamNotice (src/lib/domain/escalation/team-notice-send.ts:123): alsoSupervisedBy holds on Supervised; coworkerNoteOf sends (#19612) |
| Property email door | sendPropertyEmail (src/lib/integrations/email/property-graph-sender.ts); html? optional (:79) |
| Other send paths | tellStaff (pass-through, 19 files), raw sendEmail/sendRecapEmail (33 files), Graph direct (4 sites), holdEscalationEmail (list email) |
| Proposed, not on main | renderExternalEmail, a staff-email lint rule, a raw-send lint rule, an email-doors allowlist, check:email-doors and its mutation control |