Skip to main content
Jonathan Andrei
Back to all posts
Jul.-Aug. 202612 min read

Bloom: Nobody Cancels, They Just Stop Coming. Bloom Reads Each Client's Own Visit Rhythm, Flags the Ones Drifting from It, and Writes a Personal Note to Each. Rules Decide Who, Gemini Decides What to Say.

A typical salon loses about 40% of its clients every year, a first-timer who does not rebook within 30 days has about a one-in-five chance of ever returning, and a loyal regular is worth several hundred dollars a year. The signal is invisible because it is an absence, spread across hundreds of people who each have their own rhythm. Bloom's architecture is the idea: rules decide WHO (deterministic risk engine on each client's own median visit gap), Gemini decides WHAT TO SAY (a short note in the owner's voice, referencing that person's real history). The demo of the whole thesis is two clients: Aisha and Jane are both 44 days since their last visit; Aisha comes every 8 weeks, Jane comes every 4. Any tool that flags 'no visit in 60 days' is wrong about one of them.

GeminiXPRIZEHackerFundGoogle Gemini 2.5 FlashVertex AINext.jsPrismaNeonStripeResendClient Retention
I created this post and the Bloom project for the Google Gemini XPRIZE / Hacker.fund Build with Gemini hackathon (Small Business Services category, closes Aug 17). #GeminiXPRIZE #HackerFund
The claim in one sentence: the largest single profit leak most local shops have is not marketing, it is memory. Nobody cancels; they just quietly stop coming, and the owner finds out months later. A first-timer who does not rebook in 30 days has about a one-in-five chance of ever returning, so days 7 to 30 after a first visit are the highest-value moment in the entire business and the one nobody is watching. Bloom watches it by reading each client's own visit rhythm and flagging drift against it, then drafts a personal note the owner reviews and sends. It is your appointment book, but it reads itself.
Bloom homepage in dark mode: giant serif headline 'Nobody cancels. They just stop coming.' with an underline on 'coming'. Right side shows the client radar with six clients (Priya R, Aisha B, Jane W, Marcus D, Elena S, Nina K) and a timeline of flower-icon visits; Jane and Marcus are flagged red at 44 days, Elena is drifting, Nina has 12 days left. Subtitle: 'It is not a marketing problem. It is a memory problem.'
The whole thesis in one screen. Six clients, one timeline each, one line of prose beneath: 'Aisha and Jane were both last in 44 days ago. Only one of them is leaving.' Everything else in the product is that sentence, made actionable.

The architecture is the idea

Rules decide WHO. Gemini decides WHAT TO SAY. The risk engine is deterministic, and deliberately so. It computes the median gap between a client's real visits (median, not mean, because one six-month gap for an injury would drag a mean far enough to hide a real lapse), then scores them against their own cadence. It is exact, auditable, reproducible, and it never hallucinates: the same book always produces the same verdict, which matters when the output is 'this person is worth $1,295 a year and she is leaving.' Gemini then does what a rule cannot: reads one messy human history (what they last had done, how often they normally come, how far past their own rhythm they are) and writes them a short note in the owner's brand voice. The owner reviews, edits any line if they want, and approves before Bloom sends from the business's verified domain. Never a blast: one message, one person, once.

The two-client demo of the whole thesis. Aisha last seen 44 days ago, cadence 56 days (8 weeks), verdict green. Jane last seen 44 days ago, cadence 28 days (4 weeks), verdict red flag. Any tool that flags 'no visit in 60 days' treats them identically. Bloom stays silent on Aisha and writes to Jane.
Same last-seen date, opposite verdicts, and the calendar rule cannot see the difference. This is the single frame the entire product exists to make possible.

Nothing to migrate: whatever the owner already uses

The owner exports a CSV from whatever they already use (Fresha, Square, Vagaro, Booksy, even Google Calendar) and uploads it. Nothing to migrate, nothing to install. The parser finds the columns by keyword rather than by header name, so exports from platforms Bloom has never seen still work. Same-day rows are merged into one visit, because those platforms export a row per service line item. That part is free, because it costs nothing to show someone their own losses. What the owner sees is a client radar scoring every client against their own cadence, with what each is worth a year attached; from there, the owner triggers a win-back one client at a time. Delivery is capped per-business and globally, with atomic send-claim as the backstop so a replayed cron never doubles a message. The save is measured on the owner's own data: re-upload a fresh export, and if the client booked again after the note went out, Bloom counts it.

Bloom dashboard for 'The Corner Cafe' business: stat tiles (0 newsletters sent, 0 subscribers, 1 week of content, 4 AI actions logged), the current week's content (three posts + a newsletter subject), an AI activity log ('Rejected its own draft 65/100, rewrote it, but the rewrite scored 35/100 so it kept the original'; 'Self-QA scored 65/100'; 'Chose this week's angle'), and a newsletter subscribers panel.
The AI activity log includes rejected drafts and self-QA scores, not just the final output. That transparency is what AI-Native Operations (a scored criterion at this hackathon) is actually asking about.

The autonomous weekly agent, still shipping

Bloom started as a marketing-content agent and pivoted to retention. The pivot happened because content is a commodity: any owner can get captions out of a chatbot in thirty seconds, and I was selling something free. What none of them could get was an answer to a harder question: which of my clients am I about to lose. That is where retention now lives. Separately, the original weekly content agent still runs fully autonomously on a cron sidecar. Every Monday it picks the week's angle, generates three social posts and a newsletter in the owner's brand voice, runs a self-QA gate that rejects and rewrites its own drafts if they score below a threshold, and on Pro sends the newsletter from the verified domain. Every action lands in a live public agent feed (`/agent`) that a judge (or anyone) can watch in real time. It is no longer the headline, but it is the reason AI-Native Operations, a third of this hackathon's score, is genuinely satisfied rather than performed.

Live '/agent' feed page: 'What the agent has done · A live, unedited record of every decision and action Bloom's agent has taken in production.' Stats: 21 agent actions, 3 content runs, 0 subscribers reached, 3 businesses. Log entries: 'rewrote', 'qa', 'decide', 'generate', 'pause', 'activate' actions with timestamps and model info (gemini-2.5-flash via vertex, 5,360 tokens, 23.7s), one entry showing 'Self-QA scored 65/100. The call to action in Post 2 is a bit generic.'
Public, unedited, includes rejections. This is what continuous autonomous operation looks like when it is not curated for a demo. The cron has run every Monday since early July.
Related project

Bloom: Nobody Cancels, They Just Stop Coming. Bloom Reads Each Client's Own Visit Rhythm, Flags the Ones Drifting from It, and Writes a Personal Note to Each. Rules Decide Who, Gemini Decides What to Say.

View the project
Unsay: An AI Medication-Safety Agent that Goes Back and Un-Says What It Told You. When the FDA Escalates a Recall, It Corrects Every Named Patient It Already Reassured, in Seconds.
Previous post

Unsay: An AI Medication-Safety Agent that Goes Back and Un-Says What It Told You. When the FDA Escalates a Recall, It Corrects Every Named Patient It Already Reassured, in Seconds.

Agent memory has a failure mode retrieval quality cannot fix: stale context. Similarity to a stored memory does not prove the memory is still true. For most agents that is embarrassing. In a pharmacy it is a Class I recall. Unsay's fix is a bitemporal schema on CockroachDB (`valid_from`/`valid_to` for the world, `asserted_at`/`retracted_at` for this system's belief), and a join no vector store can express: every answer still standing that leaned on a claim version we no longer believe. The replay still works past the AS OF SYSTEM TIME horizon, and every correction is exactly-once across a region failure.

Aug. 202613 min read
coldpath: The Ollama Windows-on-Arm Build Ships with the Matrix Unit Off. One-Line Fix Filed Upstream, 5.75x on Prompt Processing.
Next post

coldpath: The Ollama Windows-on-Arm Build Ships with the Matrix Unit Off. One-Line Fix Filed Upstream, 5.75x on Prompt Processing.

I could not answer a basic question about my own Arm machine: when a local LLM runs, is it actually using the chip's matrix hardware, or silently falling back to scalar code? So I wrote the tool that answers it, pointed it at the ecosystem, and found the most popular Windows-on-Arm LLM runner cold. coldpath is a Capstone-based AArch64 disassembler that proves a binary contains SME, i8mm, and dotprod instructions; the finding is Ollama's official win-arm64 build has zero of any of them. One-line fix filed upstream (PR #17654), 5.75x recovered on prompt processing measured live on Azure Cobalt 100, gated in CI as a reusable GitHub Action.

Aug. 202612 min read