Since early June the CityChat repository has merged 981 pull requests. It's one repo for two native apps, a Go backend, the admin and business portals, the website and the data tools. I wrote CityChat's code myself, along with Claude, and a lot of my time goes into checking what the agent sessions produce. I choose the work. I test the apps myself on a phone and in the simulator, and a session has to tell me exactly what to test; no build goes to TestFlight or the stores without my OK, and before a store release the session has to list the known defects and what's still missing. Nothing reaches production until I say so.
In SanAlert, another of our apps, nothing under ios/ merges until I've seen it working in the simulator myself. Several of the rules below are ones I set myself.
For bigger pieces of work the split is simple. One session investigates against the live code and writes a plan note, with every bug pinned to a file and line. Another session, often on a cheaper model, gets one slice of that plan plus a page of hard rules - the plan and the rules are supposed to be everything it needs, and breaking any rule counts as a failed session.
Git
Never work on main; branch from origin/main in a fresh worktree. I edit the same repo while agents run and my local main is often days behind, so a session that branches from my checkout builds on whatever state I left it in.
Never use git stash when agents work in parallel, because all worktrees of a repo share one stash stack. In September eight agents were fixing things in SanAlert at the same time. One of them stashed its work, another stashed its own changes to run a test, popped the stash and got the first one's files. It noticed and gave them back, but that was luck. Now agents test against a temporary commit or a separate worktree, and the rule is in every agent's prompt.
Before anything is called ready, read what disappears and not only what was added: git diff | grep '^-', and every removed line has to match something that was asked for. I added that during the same SanAlert run, when the agents were about to touch remote branches, deploys, network policies and database migrations at once.
Proof
Paste the output of the command before saying something works. A session can say "verified" about tests it never ran, so the rules name the exact commands. For the backend it's go build, go vet and go test. For Android it's :app:assembleDebug :app:testDebugUnitTest, because compileDebugKotlin, which agents like to reach for, skips the test sources and comes back green.
An exit code of 0 doesn't prove much either. Copying a 195 MB database dump out of a Kubernetes pod with kubectl exec ... cat came back 3.5 MB short once and 4.1 MB short the second time, both with exit code 0; the process in the pod ends before kubectl has drained the stream. The fix is a trailing sleep 5 inside the pod, plus a size and sha256 comparison with the file in the pod and a retry when they differ.
If the code doesn't match the plan, stop and report. Plans are written against a commit, and by the time a cheaper session picks one up the code may have moved. A session that improvises fills the gap with a guess, and then I have to find the guess in review.
Before a merge, an independent reviewer agent reads the diff and the evidence, and a stronger model takes a second look. I added that in October, after a production promote passed the session's checks and one noisy sponsored-place test then failed about 90% of the time, because of drift on the model's side.
Production
Deploy only when I say so, in the current conversation. Merging to main deploys to staging on its own and production is a separate promote; a permission written down in an earlier session's notes doesn't count.
Never helm upgrade --reuse-values, and never restart a deployment that runs a mutable image tag. Both can ship a version or a config nobody chose.
Secrets never get printed, and never go into a file or a note. To use one in a smoke test, read it into a shell variable, don't echo it, and unset it afterwards.
The chat's prompt has defenses against prompt injection, and anything untrusted that goes into it passes through a sanitizer first: place descriptions, the user's saved memory, text from the web. Those defenses have to survive every edit to that file.
The last rule is about the token budget. In July I stopped a review workflow with 45 agents, where every finding was checked by other agents trying to refute it; a run like that uses one and a half to two and a half million tokens, and two had run that day. Now sessions verify inline unless I ask for a big review, and if they think one is worth it, they say what it would cost and let me decide.