📓 journal april 22, 2026 sat singh

drift cleanup and privatization

Two-week git drift across sunshine-fm consolidated into 8 sequenced commits. Repo flipped private before the push. The working pattern for cleaning up AI-assisted development drift.

the starting state

The ~/sunshine-fm/ working tree had 56 items of drift going back roughly three weeks: 14 modified tracked files, 29 untracked journal entries from April 9 through April 21, five untracked operating docs at the repo root, five untracked directories representing real new infrastructure (blog, radio-station, scripts, super-pacs, tools), and two untracked Cloudflare Workers (capture-draft-proxy, fec-tracker) living inside the monorepo with no version control.

This is what AI-assisted development drift looks like in practice. You ship a journal entry, you deploy, you move on. You do that 29 times. Then you look up and realize nothing has been committed to git since April 7.

the working pattern

Rather than one catch-all commit, the drift broke into 8 sequenced commits with a recon pass before execution. Read-only reconnaissance surfaced things the handoff doc had wrong — a file flagged as untracked was actually a tracked build artifact, and the two Cloudflare Workers were better off staying in the monorepo rather than getting extracted into separate repos like the AICV pattern from earlier in the day.

Each commit got its own courier prompt with explicit stop conditions. Claude Code executed one commit, reported back, and waited. This kept the scope contained even when Claude Code's momentum tried to carry past the checkpoint once (it shipped commits 4 through 8 autonomously before the audit could catch sensitive material).

Final commits: governance docs, journal nav copy fix, 29-entry journal backlog, blog surface with the first three posts, tools (super-pacs tracker and capture-draft PWA), workers (capture-draft-proxy and fec-tracker source), a single Astro build artifact, and radio-station infrastructure.

the audit that mattered

The autonomous commits got an audit pass before any push. The audit found hardcoded Icecast passwords in radio-station/icecast.xml and liquidsoap.liq — sunshine_source, sunshine_relay, sunshine_admin. Not external API keys. Not cloud credentials. Internal container-to-container coordination. But still, hardcoded strings in files about to be pushed.

The repo was public. Every existing SunshineFM org repo was public by default. Pushing the commits as-is would have made the passwords readable to anyone who stumbled onto the repo.

public to private

The decision to flip SunshineFM/sunshine-fm from public to private took about 30 seconds. The reasoning took longer. Four previous repos in the org were also public, all of them containing operational context that reveals the SunshineFM stack in granular detail — Anthropic API integration patterns, Cloudflare Worker configurations, internal pipeline architecture, content cadence, known issues documented in journal entries.

Making a media operation's source code public doesn't serve readers. The published site is already public. The repo being public just exposes operational surface to adversaries with no compensating benefit. The sunshine-fm repo is now private; the other four orgs will get the same treatment in a dedicated audit session.

what this is for

Every session that ships real work ends with a commit. Every week that doesn't produces drift. The pattern is simple and it's the only thing that keeps AI-assisted development from accumulating unreviewed code into production. 8 commits, one session, everything audited, repo private, working tree clean.

Tools: Claude (claude.ai project session), Claude Code, Git, GitHub CLI, Cloudflare Pages, Wrangler · Commits: 8 across sunshine-fm · Deploy: github.com/SunshineFM/sunshine-fm (private) · Est. tokens: ~55,000