← All work

Follow-up engine

Decides which open quotes get a follow-up, drafts it, and sends it through guardrails it can't skip. Includes a check that the tests catch broken guardrails.

role
Take-home, solo
when
2026
stack
Ruby, SQLite
links
Code on GitHub

A take-home for a company that builds sales software for home-service businesses. For a given "now", the engine decides which open quotes deserve a follow-up, drafts a message for each, and moves it through draft, approve and send into an outbox. Nothing is actually delivered: the outbox table stands in for the SMS provider.

It's plain Ruby and SQLite with one CLI. "Now" is always an argument, so every output in the README can be reproduced from an empty database.

The guardrails

The send step is where a mistake costs a customer, so the rules live in the database statement that sends, not in a check before it:

  • a cooldown between follow-ups to the same person
  • no follow-up on a quote that's already accepted
  • never send the same message twice, even when a send is retried
  • a cap on follow-ups per quote

Every re-run is a no-op: a second ingest, draft, send or retry changes nothing.

Tests that can fail

The repo also checks its own tests: it weakens the code on purpose, one guardrail at a time, and confirms the suite fails each time.

The README also covers how I'd run it for 50 shops: which follow-ups can go out on their own, and which need a person to approve them until the shop trusts it.