The Signal
How We Built the Routine Writing This Post
A cloud routine now reads a week of our own git history, decides if there is a real story in it, and drafts a post. The interesting part was not the drafting. It was everything built to stop it before that.
This week I finished a small piece of internal plumbing: a scheduled routine that reads the last seven days of activity across every repository we run, decides whether any of it is worth a public post, and drafts one if so. You are, in one sense, reading its output right now.
I want to describe what it took to build, because the interesting part was not the writing. Claude has been able to turn a changelog into readable prose for a long time. The interesting part was everything built around the writing to make it safe to run without me watching.
The easy 80%
The collection step was quick. A script walks every checkout, pulls the commits from the last week, drops the noise (formatting bumps, merge commits, dependency updates), and groups what is left into a digest. Routine, machine-made work, like our own weekly ad diagnostics, gets counted but not narrated. Everything else gets written up with enough context to turn into a story later.
The drafting step was quicker still. Point a model at that digest with a brief on tone, structure and house style, and it produces something close to publishable on the first pass.
Neither of those steps is where a business like ours gets exposed. The exposure is in the last 20%.
The part that actually took the work
We run one repository for our own site and thirteen others: a Business OS with live client detail, and client repos, each under its own confidentiality terms. A routine that summarises "everything that happened this week" has to sit next to all of that and still produce something that is safe to publish without a human reading every line first. Three things had to be true before I would let it run unattended.
It has to know what it is not allowed to say. There is a standing list of every client and prospect name, matched before anything is drafted, and a separate rule for anything that smells like a fee, a currency figure or a performance number. Client work still shows up in the source material. It just never reaches the draft with a name attached, and this week's run correctly left an entire client-facing story out rather than write around the name.
It has to check its own work before anyone else does. A second, much narrower script reads every draft and looks for exactly the failure modes that matter here: banned terms, currency amounts, broken links, a missing author, a punctuation mark we do not use in our own writing. It is not a style linter. It is a gate, and a draft that fails it does not go anywhere, including back to me for a decision. It just gets dropped, with the reason logged.
It has to earn autonomy in stages. The routine does not publish to the live site yet. Right now it stops at a drafts folder and posts to Slack for review. Flipping it to publish on its own is a one-line change to a mode flag, and that change does not happen until the draft-only version has run cleanly for long enough that the failure modes are no longer theoretical.
The actual lesson
None of this is specific to writing blog posts. It is the general shape of giving an AI system a task with real consequences attached: build the refusal mechanism before the generation mechanism, and let it run in a mode where a mistake is merely embarrassing before you let it run in a mode where a mistake is public.
The part everyone wants to talk about with AI systems is what they can produce. The part that actually decides whether you can trust one is what it refuses to produce, and whether you built that in before you needed it or after something went out that shouldn't have.
Find out where your marketing architecture is breaking down.
