AI coding assistants can significantly increase development speed. However, ensuring we can trust their outputs is a key challenge. Common difficulties include reviewing large, unmanageable diffs, losing context across coding sessions and dealing with partially functional code resulting from the AI changing focus mid-task.
So, I wanted to find a workflow that would tackle some of those risks and will:
Reduce the cognitive load of reviewing AI generated code.
Allow me to walk away from a session and pick up later without re-explaining context to AI assistant
Keep the codebase stable so the AI can't silently drift.
I tested this by building tiny-event-bus — a type-safe, zero dependency event bus built using GitHub Copilot with Claude Opus 4.6. The workflow has three parts: milestones that break work into small reviewable chunks, review gates at two frequencies and a living context file for AI project memory across sessions. In this blog post I’ll explain more about those milestones and why I think they’re important in AI-assisted software development.
Development planning with AI assistance
I spent the first session not writing code but just describing what I wanted and the AI proposed a plan: tech stack, package structure, milestone breakdown. Once agreed, the AI drafted AGENTS.md and MILESTONES.md in plan mode, reviewed and iterated by me before any code was written. AGENTS.md is a compact context file under 200 lines, updated after every milestone so fresh sessions start with current context.
Milestones keep code reviews small
The AI can produce a 40-file diff in minutes. Milestones fix this by breaking every feature into chunks small enough to review in one sitting. Each milestone leaves the codebase compilable, tested and documented.
Every feature starts in plan mode and the AI proposes a breakdown. Specifically, it looks at which layers it touches, how many milestones and in what order. Ordering comes from dependency analysis, not rigid sequencing and we iterate until it makes sense. The AI then updates MILESTONES.md with the agreed milestones, each one marked "not started". Finally, I review the plan before implementation begins.
"A feature is never one milestone."
Take the ability to subscribe to all events on the bus — the onAny event listener. Its implementation became four milestones:
Core implementation — add the onAny feature to the event bus.
A React hook — a wrapper that ties the listener to the react component lifecycle.
Demo update — wire it into the example app.
End-to-end verification and docs update — this will prove the API works end to end and make it discoverable.
After the first milestone, the core works and all tests pass. The React hook doesn't exist yet, but nothing is broken. You could push and come back later.
Take another example of the monorepo migration to support feature extensions to the event bus via a plugin architecture. It became five milestones:
Scaffold the workspace structure.
Extract the core package.
Extract the React plugin.
Full workspace verification.
Migrate the example app to workspace dependencies.
Contrast this with the AI doing the entire migration in one shot: a 40-file diff where you're checking peer dependency declarations while also verifying import paths. That review will be miserable! Reviewing in small chunks, though, is easy because you actually read and think about it. Milestones turn code review from an audit into a conversation.
Review gates catch drift early
Review gates keep each milestone honest. I frame these as gates rather than loops because the defining characteristic isn't the repetition, but the fact that the AI must stop and await explicit permission to proceed. This ensures that nothing is integrated into the codebase without passing through human review.
This is a deliberate contrast with fully autonomous approaches like the Ralph Loop, where the AI runs in a continuous cycle - code, test, fix, repeat - with minimal human intervention. While the Ralph Loop prioritizes velocity, it creates obstacles for human oversight due to the rapid generation of massive code volumes. This speed can lead to the compounding of incorrect assumptions. Gates trade speed for control, and is still dramatically faster than writing everything yourself.
There are two review gates, operating at different frequencies. The inner gate fires after every individual test which is also the smallest reviewable unit and catches a wrong assumption before it propagates. The outer gate fires at milestone boundaries and checks whether the completed feature fits the bigger picture and whether the codebase is in a stable state to hand off or continue later.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.