Twenty-plus years of infrastructure engineering taught me what undisciplined change does to production systems — so before AI wrote a line here, I wrote the rules it works under. Every project in the portfolio — SouthpawStrings, desk-engine, the AI Orchestrator, this site — is delivered the same way: AI agents draft, investigate, and implement at speed, and I review, gate, and own every consequential step. The split is written down as working standards in the repositories themselves, so any agent (or any future session) inherits my rules instead of improvising its own.

The documentation happens while the work happens, not after. Every repository carries a changelog entry and a version bump with every release; sessions end with a written checkpoint — what changed, what was decided and why, what is unresolved, and the exact next command — so the next session (human or AI) resumes safely instead of guessing. Decisions get recorded with their reasons: half the changelog entries in these repos read as short engineering post-mortems, because that is what they are.

The deployment standard

A release reaches production only through the repo

No hand-typed deploysScripts, or it didn’t shipEvery deployable project carries its release path as committed scripts. A hand-run build or a kubectl command typed at a prompt is treated as an incident waiting to be written up — the standard exists because one was.
Fail closedDirty trees refuse to buildBuild scripts refuse an uncommitted or unpushed tree — the build host builds a commit, and anything uncommitted is a stale deploy wearing a fresh deploy’s clothes. Database migrations take a verified backup first or refuse to run.
Deliberate commitmentPreview first, typed confirmationDeploy scripts dry-run by default and show exactly what would change. Committing takes a typed confirmation or an explicit flag — never satisfiable by a stray keypress or a piped “y”.
Truthful manifestsPinned by digest, in gitImages are pinned by content digest into tracked manifests — never patched live — so the repository always describes exactly what is running, and a rollback is a one-file apply named in advance.
Proof, not vibesVerify afterwards, specificallyA rollout finishing is not the same as the release working. Scripts assert the version the service reports, its health endpoints, and its fail-closed behaviour — and say precisely what failed when something does.
Drilled, not assumedRollbacks get rehearsedThis site’s own v1.0.0 cutover ended with the rollback applied live — the old site came back in one Recreate cycle — and only then rolled forward for good. An untested rollback is a hope, not a plan.

Engineer-led AI, in practice

Agents draft; a person decides

The AI side of the lifecycle is deliberately boring: agents do the long, careful work — reading whole codebases, porting pages, chasing a DNS race through nginx internals — and every irreversible step routes through me. Pushes and production deploys sit behind explicit in-session confirmation; secret scanning guards every push; guarded scripts make the safe path the easy path. I am deeply sceptical of model output until it has been checked, constrained, and tested in the real operating environment — that scepticism is a working control here, not a slogan.

The speed is real, but it is the dividend of the discipline, not a substitute for it. The v1.0.0 rebuild of this site — content ports, the desk shell, the container path, the staged cutover — landed in a single working day because years of groundwork already existed: standards to follow, reference implementations to copy, checkpoints to resume from, and an engineer who knew exactly what “done and verified” had to mean. The AI Orchestrator is the same philosophy productised: my approval gates and evidence trails, as software rather than willpower.

And when something breaks anyway, the failure becomes a standard. An hour-long outage caused by nginx resolving an upstream at config-parse time became a written pattern every proxy config here now follows; a build host silently filling with layer cache became a “clean as you check” rule every build script implements. The lifecycle grows a clause every time reality wins an argument.