// teardown
The weekly changelog
A habit that survives a busy week.
Thursday
Review window
Friday
Every 15 minutes
// overview
Every Thursday an agent drafts the product changelog from the issue tracker, merged code, and meeting notes. The reviewer has until Friday morning to approve, hold, revise, or edit it, and then it publishes unless someone held it: to Slack, to email, and as narrated audio. Drafting is the easy part. The design work is making silence a safe default: a drafter that can only read, a save step that checks its claims, a publish step that can't double-send, and failures that reach a person before Friday.
// how it works
01 · schedule
Eastern time on a UTC clock
Convex crons run on UTC, but the schedule is stated in Eastern time, whose UTC offset changes twice a year. So each schedule is registered twice, an hour apart. Thursday drafting and Friday publishing both fire at both candidate UTC times, and the action checks the real Eastern hour and returns early on the wrong one. Both crons derive the week from one shared function, so they always agree on which entry they mean. Only the production deployment acts.
02 · draft
A one-shot agent that can only read
At 12:30 on Thursday the cron opens a run and dispatches a single turn to the changelog mode. The agent reads the week through purpose-built tools: pipeline stages built from GitHub branches and the issue tracker, commit detail, week-over-week aging, and meeting notes. Repo access is file reads and grep over a fresh clone, with no shell and no write tools, and the one subagent type it may spawn gets the same read-only set. The turn has a 20-minute ceiling.
03 · narrate
Heard before it ships
When a draft saves, a model rewrites it as speech at three lengths: a 90-second summary, a four-to-five-minute walkthrough, and a deep dive built from the run's full tool log, covering what the entry left out. Audio is cut right away, so the reviewer can listen on Thursday. Everything is keyed to hashes of its source words, so an edit regenerates the narration and a no-op save costs nothing. A deep dive that names a person or lifts a line from its sources stays silent until a human clears it.
04 · review
Four responses, none required
The reviewer gets a Slack DM with the summary, a count per stage, any source that came back empty, and four buttons: Approve, Hold, Revise, and a link to the editor. Approve and Hold update the entry and rewrite the DM, so nothing fires twice. Revise collects notes in a modal and dispatches a fresh agent turn, and if that turn fails, the prior draft stands. The in-app editor pairs the MDX source with a debounced live preview and inline compile errors.
05 · publish
A state machine, not a send
Friday at 9:00 Eastern, the publish action finds the week's entry and makes one atomic decision. Draft or approved: mark it published. Held: skip silently. Already published: do nothing. No entry: alert the reviewer and send nothing, so a failed week never becomes an empty email. The editor's Publish now button runs the same transition, so a cron racing a click can't publish twice. Slack and email go out only after the status write commits.
06 · distribute
One entry, three surfaces
Publishing posts to the product channel in Slack and emails the whole team through Resend. The Slack post is the announcement and the player at once, carrying the narrations as playable audio, with a plain post as the fallback. The email is a standalone digest of headline numbers, shipped items, and stage counts that links to the full entry, since interactive demos can't survive an inbox. The in-app reader opens published entries to anyone with a login. Each leg is best-effort.
07 · recover
Failures stay small and loud
The drafting turn runs asynchronously, so nothing reports a process that dies mid-run. Every 15 minutes a sweep marks any run still running after 30 minutes as failed, records the best diagnosis available, and DMs the reviewer. The sweep re-checks status inside its own transaction, so a draft that lands mid-sweep wins. Each week is keyed to its own publish date, and the shipped diff starts from the last entry that landed, so a lost week's work rolls into the next one.
// decisions
The parts that were a call, not a default — and what the alternative would have cost.
Publish unless held
Publish only after an approval
An approval gate turns a weekly habit into a weekly chore, and the first busy Friday breaks the streak. The failure worth designing against is a missing week, not an imperfect one: the entry is internal, the reviewer has most of a day with it, and holding is one click. That inverts the proposal-first rule in /systems/ai-harness on purpose, and the exception stays narrow. The drafter's only write is its own draft, and edits from the interactive assistant still arrive as proposals.
A mode inside the shared AI harness
A dedicated changelog service
Everything that made it look like its own service is data: a system prompt, a tool set, and a one-shot lifecycle. As a mode it runs on the harness runtime with no new deployment, and every run opens the same kind of agent session as any other conversation, so a bad draft is debugged from a full tool transcript stored alongside every other agent run. How modes work is covered in /systems/ai-harness.
Shipped means it reached the production branch
Shipped means closed in the issue tracker
Every tracker column depends on someone dragging a card, so every column drifts. Branches don't. Stages come from git, and the shipped diff starts from the branch tips the previous entry stored rather than from commit dates, because a fast-forward promotion keeps its original dates. The tracker still supplies titles, context, and new work with no code yet. A ticket closed with nothing placed this week reaches the reviewer as a question, never the entry as a claim.
Rules enforced by the save tool, with a refusal budget
Rules requested in the prompt
A prompt can ask the agent to include everything that shipped. Only a check can make it. The save tool refuses a draft that files work under a stage the sources didn't report, names a person, or quotes meeting notes. Two gates get a budget instead: missing shipped work, whose fix can loop, and a summary check that leans on a word count. Each refuses twice, then the draft saves with the gap listed for the reviewer, because a named hole beats no entry.
// guarantees
Held means held
A held entry never publishes. The Friday cron and the manual button share one atomic transition, so no entry goes out twice.
The drafter can't touch code
File reads and grep, no shell, no write tools. Its one write is a draft checked against the sources, and every tool call is recorded.
Failures reach a person
A stalled run is swept and reported within 45 minutes. A Friday with no entry alerts the reviewer and sends nothing.