โ† all sprint docs

๐Ÿ”ด HELLO@ EMAIL RULES โ€” the law for every 1:1 email sent from hello@themovementathlete.com

Set by Aga, 31 July 2026. Governs every email the retention rail sends or drafts from hello@themovementathlete.com: R1 cancel-save, the T-30 watcher, dunning/payment-recovery, failed-purchase, reply-fulfilment, concierge, upgrade stages โ€” and any lane added later.

The one sentence that decides every question below:

It has to look like Jesse just typed it.

These emails work because they are indistinguishable from a personal message. Every rule here exists to protect that. When a new idea conflicts with it, the idea loses.


โš ๏ธ First: this is NOT the marketing email estate

Two completely different systems share the word "email". Never apply one's rules to the other.

hello@ 1:1 rail (this document) Marketing estate (ActiveCampaign / Customer.io)
What Personal notes from Jesse to one member about their account Campaigns, sequences, broadcasts
Looks like A person typed it A designed email
Governed by This file CLAUDE.md EMAIL RULE โ†’ /email-fleet, locked footer, email_lint.py, white canvas, design guide
Template None. Ever. Canonical template, mandatory
Sent by Gmail API from hello@ AC / CIO

Running these through the marketing fleet would destroy the thing that makes them convert. Running marketing emails under these rules would fail the lint gate. Keep them separate.


THE RULES

1. No styling. None.

No bold. No underline. No italics. No colour, no headings, no dividers, no images, no logo, no footer bar, no background colour, no buttons. A person writing to one other person uses none of these. (Aga, 31 Jul: "remove the bold so it really looks like Jesse just typed it.")

The renderer supports **bold** / _italic_ / __underline__ markers โ€” do not use them in lane copy. They exist only so a future exception can be made deliberately, not by drift.

Note the deliberate difference from the marketing law. The estate rule ("bold the key line, italic the human beats, one underline") is correct for campaigns and wrong here. Same goal โ€” easy reading โ€” opposite means: in a personal email, readability comes from short paragraphs, not from formatting.

2. One idea per paragraph. Short paragraphs.

This is how people actually type, and it is the ONLY readability tool available under rule 1. Never stack the bad news, the reassurance and the instruction into one block. Break them.

3. Links must be clickable โ€” never a bare URL to copy-paste.

(Aga, 31 Jul: "make a link an actual clickable link โ€” instead of a dead link they need to copy and paste.") A URL sitting on its own line becomes a real anchor. - Standard link blue #1155cc โ€” Gmail's own. Not a brand colour: branded links read as a campaign at the exact moment we need trust. - Keep the โ†’ arrow โ€” under rule 1 it is the only visual cue the text is clickable. - Built automatically by r1_lib.build_message() / text_to_html(). Never hand-build MIME.

4. Anchor text: descriptive, honest about the destination, CRO-reviewed.

Never "click here" (generic, tests poorly). Never over-promise what the first screen shows. - Dunning โ†’ Fix your billing โ†’ โ€” task-framing. It must NOT say "Update your card", because the link lands on the Stripe login page (enter email โ†’ Stripe sends a sign-in link โ†’ then the card form). Promising a card form and delivering a login box creates doubt on a billing page, which costs more than any click-rate gain. - R1 cancel-save โ†’ Keep training โ†’ โ€” outcome-framing. They chose to leave; administrative language reads as the process they already rejected. The email's real goal is a reply. - Different lanes get different anchors on purpose โ€” the member's psychological state differs. Any new anchor goes through the email-copywriter agent first.

5. multipart/alternative โ€” the plain-text part is ALWAYS kept.

text/plain (markers stripped, bare URL) + text/html (the clickable twin). Non-negotiable: - plain-text clients and forwards must work; - send_payment_drafts.needs_aga() reads the plain part โ€” lose it and the safety gate goes blind (audit finding L1); - a body with no link stays pure plain text โ€” no HTML part at all (e.g. failed-purchase notes, guardian alerts). Don't add HTML for its own sake.

6. The reply is a feature, not a fallback.

Reply-to is always hello@, a human reads it, and the copy says so. Where a lane can convert on a reply instead of a link (failed-purchase: "hit reply and I'll send you a fresh link"), prefer the reply โ€” it has no links to distrust and it starts a conversation. Every lane's subject must be watched by reply_fulfil.py so STOP suppresses and a live reply is surfaced. (This was missing until 31 Jul โ€” audit finding C1.)

7. Two closing beats, always.

8. Signature and footer, verbatim shape.

Jesse
Head Coach, The Movement Athlete

--
You're receiving this because <the specific reason>. This isn't a marketing campaign.
Reply STOP and I won't email you about it again.

Jesse is Head Coach, never "founder". Say why they're getting it, in one honest clause. The STOP promise is real โ€” rule 6 makes it work.

9. Never blame the wrong party; never fabricate.

Copy branches on the actual failure reason (bank block vs card details). No invented urgency, no fake deadlines, no claims we haven't verified. If we caused it, say so.

10. Nothing sends itself.

Every member-facing message is a Gmail draft waiting for Aga. Three explicit exceptions โ€” the R1 T-30 watcher, the upgrade stages (both --live, templated pre-approved copy), and the 14-hour auto-send rule scoped to the dunning lane only. A new lane arms drafts-only.

11. Arming a lane = copy review + audit + docs, then execute.

Aga's pre-flight law: run the copy through the email-copywriter (CRO) seat, audit the whole job family for bugs, document it into the register + cockpit โ€” then arm.


Where this is implemented

Thing File
Renderer (multipart, links, markers) tools/retention/r1_lib.py โ†’ build_message() ยท text_to_html() ยท strip_markup()
Dunning copy + anchor tools/retention/payment_recovery_lane.py (BODIES, make_draft)
R1 copy + anchor tools/retention/copy/seg-*.txt ยท send_r1.py ยท pre_expiry_watch.py
Failed-purchase copy tools/retention/failed_purchase_lane.py (no links โ€” reply mechanic)
Reply + STOP capture tools/retention/reply_fulfil.py (PAYMENT_SUBJECTS)
Safety gate tools/retention/send_payment_drafts.py (needs_aga)

Canonical companions: docs/company/GOVERNANCE/AUTOMATION_JOB_REGISTER.md (what each lane does) ยท JOB_AUDIT_FINDINGS_2026-07-31.md (known bugs + open items).

Changing any rule here changes what a real member receives. Update this file in the same session, or it is drift.