The private-nudge rule
A nudge is always private. Ever Async never corrects anyone in public.
This is not a preference or a default. It is the constraint the rest of the system is built around, and it is stated as such in the code that renders every outbound action:
//! Design rule: nudges are ALWAYS private (ephemeral or DM) — the
//! bot never corrects anyone in public.
Why
A bot that publicly says "your message was unclear" is a bot that gets uninstalled inside a week. Not because it was wrong — often it is right — but because of what a public correction is in a work channel:
- It is a status event. The author's colleagues watched a machine grade their writing in front of the team.
- It is contagious. Once one person has been corrected publicly, everyone else writes defensively or stops posting in that channel.
- It is unfixable. You cannot un-see it; deleting the nudge makes it worse.
- It is worst for exactly the people it should help most — non-native speakers, new joiners, junior engineers.
A private nudge inverts every one of those. Nobody else knows it happened, the author fixes the message and looks good publicly, and the cost of a false positive drops from "a person is embarrassed" to "a person dismisses a message". That gap is the whole reason the product can exist at all.
What "private" means in practice
| Situation | Channel action | Who sees it |
|---|---|---|
| Nudge, no rewrite available | Ephemeral | the author only |
| Nudge with a suggested rewrite | EphemeralWithButtons | the author only |
| The author presses Post this | ThreadReply | everyone — because the author chose to |
| Digest | DirectMessage | the recipient only |
On Slack this is chat.postEphemeral: the message is not stored in channel
history, other members never receive it, and it disappears on reload. The
author is the only human in the loop.
The one public thing Ever Async ever posts about a specific message is a context card — and a context card is not a correction. It adds the missing link. Nothing in it says the author did anything wrong.
The grace window: let people fix it themselves
A nudge is never immediate. When the pipeline decides a message is low-context
it schedules the nudge for [policy] nudge_delay_secs later (default
150 seconds) and persists it.
During that window, anything the author does to fix the message cancels it:
- A thread reply from the author — they added the detail themselves.
- An edit of the original message — same.
- Any thread activity marks the conversation as moving.
When the timer fires, storage is re-checked for an author follow-up before
anything is sent. If one exists the nudge is dropped and
ever_async_nudges_cancelled_total increments. This counter is worth watching:
a high cancel rate is not a failure, it is the product working — people are
self-correcting, which is exactly the behaviour change you wanted.
What a nudge actually contains
Three parts, in this order:
- The reasons — one short human sentence each, phrased for the author, not for a log. "'the PR' has no link — readers would have to search for it."
- The charter it is citing — the team's own rules, so the bot is enforcing your norms rather than its opinion. See the charter.
- A suggested rewrite, when an AI provider is configured — plus the buttons.
One click, never homework
The rewrite ships with two buttons:
| Button | action_id | Effect |
|---|---|---|
| Post this | post_rewrite | posts the rewrite into the thread, attributed to the author |
| Dismiss | dismiss | acknowledges and closes |
This matters more than it looks. A nudge that says "please add more context" assigns work; a nudge with a ready message and a button saves the author time. The product only survives if the nudge is a favour.
The button payload carries everything needed to post — thread root and rewrite
text — so a restart never orphans a pending button, and there is no server-side
session to lose. Accepted rewrites are counted in
ever_async_rewrites_accepted_total: that counter is the honest measure of
whether the suggestions are any good.
Slack allows 2000 characters in a button value. Rewrites are capped so a suggestion always fits; an oversized or expired payload degrades to "That suggestion expired. Just post the details in the thread." rather than failing silently.
The rules this implies elsewhere
- Ever Async never posts as the author. Auto-posting a rewrite would make the private nudge pointless: the correction becomes public again, and now the author did not even write it. Cut from the MVP deliberately.
- Sensitivity defaults to conservative. A private nudge is cheap but not free. See sensitivity.
- Quiet hours suppress nudges, not context cards. A card is useful at 3am; a nudge at 3am is a notification nobody asked for.
Turning it off
Per conversation, at any time, by anyone in the channel:
/async off
No admin approval, no ticket. A tool that people cannot switch off is a tool they campaign against.