Email standards: two we have, used inconsistently

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

TL;DR

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.

The standards, the audit, production, the map and the plan
6
sender files on the team note
3
sender files on the prospect email (181 real sends in 3 weeks)
9
other email looks in live code
6
ways an email leaves the app

1. The two standards

Standard 1: teamStandard 2: outside
Who gets itThe customer's office staff, reviewers, our own teamTenants, prospects, applicants, vendors, owners
Looks likeA plain note from a coworker, small Propflow logo at the bottomThe 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 mainemailPlainNoteLayout (agents/clara/lib/messaging/transports/stripe-base.ts:259) + CLARA_SIGN_OFFbuildClaraReplyHtml (clara-reply-template.ts:338) + buildClaraReplyPlainText (:223)
DoorTeam-notice door, sendOrHoldTeamNotice (team-notice-send.ts:123)Property email door, sendPropertyEmail (property-graph-sender.ts)
RulingNever 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

Standard 1: a plain note from Clara

Desktop, 640

Monthly renewal list email at desktop width

Phone, 375

Monthly renewal list email at phone width
Exemplar: the monthly renewal list, rendered from main (render-batch.ts:224) with made-up rows. Not yet sent to a customer.

"Tenant said yes", 640

Said-yes office note on the plain frame

375

Said-yes office note at phone width

"Tenant countered", 640

Counter office note on the plain frame

375

Counter office note at phone width
The two office notes as proposed in #19700 and #19701 (open). On main both still use the old card.

Standard 2: the prospect reply email

Desktop, 640

Prospect reply email at desktop width

Phone, 375 (does not shrink)

Prospect reply email at phone width, overflowing
Clara's reply to a prospect, rendered from main. The phone shot is 600 px wide: the card overflows.
Tour confirmation email, a hand copy of the same frame
Tour confirmation: a hand copy of the same frame (tour-reply-template.ts:120).
#Finding on Standard 2 (verified at main)Where
1The 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
2The card is a fixed 600 px table with no phone rule; it overflows on a phone.clara-reply-template.ts:357
3The tour confirmation is a hand copy of the frame, not the helper.tour-reply-template.ts:120, :229, :267-271

2. Double audit

An independent Fable re-audit re-checked the first audit against main and the send log. Where they disagree, the re-audit wins.

#ClaimAudit 1 saidFable re-auditEvidence
1Team emails on the note26 of 60; 34 offUnverifiableNo list, no unit. By file: 6 senders use the plain-note shell.
2Team emails through the door6 of 60Confirmed6 caller files of sendOrHoldTeamNotice; none of them uses the note shell. (7 since #19612.)
3Outside emails on the standard0 of 28RefutedMeasured against renderExternalEmail, which does not exist. The real standard carries 148 replies + 33 first emails.
4Outside count28 (TL;DR) and 36 (footnote)RefutedSelf-contradiction. By file: 14 door callers + 5 direct + account/website mail.
5Outside looksTwo branded looks + raw textRefutedFour HTML shells reach outside audiences, plus a hero frame, plus 5 text-only senders.
6The note is a shared helper used by the list emailYesConfirmedrender-batch.ts:224, compose.ts:181. Paragraphs are still hand-built per sender.
7The counter note uses the noteYes, own fileRefuted since changedNo such file at the re-audit snapshot. #19612 added it after: card frame, sent under Supervised. Plain frame is #19701.
8coworkerHtml locationstripe-base.ts:259RefutedLine 259 is emailPlainNoteLayout. coworkerHtml is private, preview-only.
9Said-yes note uses the cardYesConfirmedrenewal-yes-office-notice.ts:37, :110
10Team notes "never held" under SupervisedNever heldRefutedThat is the ruling, not today's door: alsoSupervisedBy holds on Supervised (team-notice-send.ts, #19492). No real company has Renewals Supervised today.
11Two doors cover every sendYesRefutedtellStaff (19 files) is a pass-through; 33 files call the transport directly; 4 Graph-direct sends; owner report raw.
12Team sends skipping the switch or test guard25RefutedUndercount: 28 production sites; company-live-gate.ts:322-328 sends before the test check.
13Supervised holds tenant and prospect mailYesConfirmedWith a gap: an approved prospect redraft goes out as text with no frame (bake-gate.ts:2250).
14Clara sign-offs on outside mail8UnverifiableAt least 3 forms found.
15Design guide is staleLast updated 07-09RefutedUpdated 10-14 (#19625); step 0 is done.
16Checks and helpers listed in ReferenceListed with pathsSplitImplementable, but renderExternalEmail, the staff-email lint rule, check:email-doors and its control do not exist.
17Counts pinned to linesAt two commitsUnverifiableLines drifted; pin to files.
18Inventory completeYesRefutedThe lockbox-missing alert to prospects is in neither audit.

Corrections

  1. Look and send path are separate; old counts mixed them.
  2. The outside standard exists and carries most outside mail.
  3. The team door holds under Supervised (#19712).
  4. Six "shipped" checks do not exist.
  5. Counter note: row 7.
  6. Design guide already fixed.
  7. One prospect sender was missed.
  8. Vendor stub path was wrong.
  9. 7 companies (6 real), not 11.

3. Production reality, 09-23 to 10-14

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)ToRealTestNot delivered (real)Last realLook
Clara replies, "Re: …"prospects, tenants1483613 bounced, 1 blocked10-14Standard 2
"Your inquiry about <home>"prospects332010-14Standard 2
Follow-ups, "Still looking"prospects29126010-14brand shell
Tour next stepsprospects80010-13brand shell
Tour confirmed / cancelledprospects613010-02text only
Renewal offer readytenants502 blocked, 1 bounced10-12hero / card
Owner weekly reportowners300—digest
Website thank-youvisitors11010-07marketing
Caller and question handoffsstaff~250~35011 + 8 blocked10-14Standard 1
Bake alertsour engineering1880010-14own HTML
"Asked us something we could not answer"staff612834 blocked, 5 lost10-14Standard 1
Tour confirmed (office copy)staff384735 lost10-14card
New application / lease readystaff311010-04card
Lead escalated (sender since removed)our inbox280009-30—
Sign-in codeaccount250010-14card
Still waiting on your reviewstaff150010-03card
Emergency / Urgentour inbox1441010-11Standard 1
Team inviteaccount81010-06card
Tour updatestaff617010-06card
Leads to call this weekstaff40010-14digest
Renewal completedstaff402 lost10-12card
Promise-backing notesstaff416010-04Standard 1 / hand-built
Sign-in link; internal notesaccount, staff3 + 30010-10card
Renewal counter ("Action needed")staff2924 lost10-02hand-built
New lead; guest card not created; month-to-monthstaff1 each23 / 6 / 05 lost09-30hand-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).

Incidents in the window

What happenedLostWhen
Failed staff-notice rows blamed on a missing email key: false alarm, written by local scripts, not production0 real (42 script rows)checked 10-14
A nonexistent test mailbox (smoke@) plus 20 bench aliases on the bounce list; test traffic only106 drops (log saw 28)10-03 to 10-09, stopped
Blocks to an undeliverable harness address; test traffic only17109-23 to 09-29

Key incident: false alarm (staff notices failed only from local scripts)

4. Consistency map

Every off-standard sender and where it moves. No new helper.

Sender(s) todayMoves toLook todaySend path today → after
Renewal completed, holdover, lapse digest, said-yesStandard 1carddoor already
Key pickup, new-lease draft, move-out mismatch and draft, vendor outcome, PO required, stale dial, action reminders, office tour confirmations, tour updateStandard 1cardtellStaff / raw → door
Renewal counter (older path), guest-card failure, reply release, owner escalationStandard 1hand-builttellStaff / raw → door
Leads to call this weekStandard 1digestdoor already
Missed call, promise alarm, decision request, emergency, team-notify engineStandard 1 already—raw → door
Prospect thread copy to staffStandard 1reply cardproperty door → door
Notes behind the teamNotifyEngine switch (on at 2 of 6 companies)Standard 1 (engine path)two frames by companyretire the switch
Bake alerts (188)Machine alert: stays plain (D1 A)own HTMLraw
Sign-in code, sign-in link, invite, PMS connectD2cardraw
Tour confirmationStandard 2hand copyproperty door already
Application link, lockbox code, lockbox missing, congratsStandard 2brand shellproperty door already
Follow-up touches + 4 scheduled outreach jobsStandard 2brand shellGraph direct → property door
Inbound-address replyStandard 2 already—Graph direct → property door
Renewal offerStandard 2hero / card / brand shellproperty door already
Desk-booked tour, property reply, PMS application, vendor completion, PMS emailStandard 2 (HTML + text)text onlyproperty door already
Approved prospect redraftStandard 2empty HTMLproperty door already
Waitlist approvedD2cardraw
Owner weekly reportStandard 2 (fit of a table report: Fede's call, below)digestraw → property door
Newsletter and demo thank-yousD2marketingraw
Vendor dispatch, quote, chase, turnoverStandard 2 when vendor mail turns onbrand shellraw / Graph → property door

Our own account emails: 8 emails, three layouts

EmailLayoutFromBrand casingSign-off
Sign-in codecardClaraPropFlownone
Sign-in linkcardClaraPropFlownone
Team invitecardClaraPropFlownone
Waitlist approvedcardClaraPropFlow"— The PropFlow team"
PMS connect (IT admin)cardClaraPropFlownone
Welcome (never sent)guide—PropFlow"— The PropFlow team"
Newsletter thanksmarketingPropflowPropflow"The Propflow team"
Demo thanksmarketing, old "PropFlow.ai" logoPropflowmixed"The Propflow team"

The logo and brand cheat sheet say "Propflow"; 6 of 8 emails say "PropFlow".

Gallery: the 8 account emails as sent today (synthetic data)

Sign-in code

Sign-in code email

Sign-in link

Sign-in link email

Team invite

Team invite email

Waitlist approved

Waitlist approved email

PMS connect

PMS connect email to an IT admin

Welcome (never sent)

Welcome email

Newsletter thanks

Newsletter thank-you email

Demo thanks

Demo request thank-you email with the old logo

5. Delete list

#WhatWhy it is deadRisk
Done 10-14"PropFlow AI Agents - Daily Summary" emailA scheduled job on Fede's Mac, not production code; schedule uninstalled on Fede's instruction—
1Welcome email + its guide layoutOnly the admin preview uses themnone
2Tour-request emailPreview and a dev-only routenone
3Renewal accepted / declined staff emailsTests onlynone
4Tour reminder email builderNo job imports it; reminders go by textlow
5Old manager-escalation buildersPreview and a voice harness onlylow
6Dev "send test email" routeNo auth inside; relies on the production 404low-medium
—Gas / urgent subjects, lead-watchdog emailAlready removed (#14337, #14029)—

Fede's call (yes / hold)

6. Decisions

  1. Decided A (Fede, 2026-10-14) Do our own engineering alerts count as "internal team"? A) Human-read digests (sync digest, metrics, knowledge review, demo request) yes; machine alerts stay plain text. B) All of them. C) None. Recommend A.
    Human-read digests (sync digest, metrics digest, knowledge review, demo request) use the coworker note; machine alerts stay plain text.
  2. Pending Propflow account emails: which standard?
    a) Do sign-in and invite emails count as team email (Standard 1)? Recommend yes, "Propflow" casing.
    b) Do website thank-yous fall under the ruling at all? Recommend no: keep their layout, fix casing and the old logo.

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.

7. Plan

No building tonight (Fede). After this week's renewals flip is proven:

  1. Deletions first.
  2. One helper per standard owns logo, wordmark, From, footer and sign-off, on the two existing helpers.
  3. Door matches the ruling: one mechanism, never held (#19652, #19712).
  4. Each off-standard sender moves in one small PR.
  5. Last, a build check fails any email building its own HTML or calling the mail service directly.

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.

Reference (for agents)

Code names behind each plain term
Plain termCode on main
Team noteemailPlainNoteLayout({ 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 emailbuildClaraReplyHtml / 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 / guideemailCardLayout (stripe-base.ts:167), emailMarketingLayout (:318), emailGuideLayout (:391)
Team-notice doorsendOrHoldTeamNotice (src/lib/domain/escalation/team-notice-send.ts:123): alsoSupervisedBy holds on Supervised; coworkerNoteOf sends (#19612)
Property email doorsendPropertyEmail (src/lib/integrations/email/property-graph-sender.ts); html? optional (:79)
Other send pathstellStaff (pass-through, 19 files), raw sendEmail/sendRecapEmail (33 files), Graph direct (4 sites), holdEscalationEmail (list email)
Proposed, not on mainrenderExternalEmail, a staff-email lint rule, a raw-send lint rule, an email-doors allowlist, check:email-doors and its mutation control
PropFlow Docs