Speed that maps onto the two acts
The product uses AI; it was also built with AI assistance, and that combination is most of the reason a small team could reach a working MVP, and then a growing team could cement a full platform, inside nine months. The commit-velocity curve maps onto the two acts:
| Month | Commits | Act |
|---|---|---|
| 2025-09 | 36 | I — MVP sprint begins |
| 2025-10 | 232 | I |
| 2025-11 | 253 | I |
| 2025-12 | 276 | I |
| 2026-01 | 360 | I to II — MVP lands, team forms |
| 2026-02 | 453 | II — team cementing the platform |
| 2026-03 | 821 | II |
| 2026-04 | 1,115 | II — peak parallel throughput |
| 2026-05 | 409 | II |
| 2026-06 | 93 | II |
The Act II ramp is two effects compounding: more contributors and higher throughput per contributor as AI-assisted workflows matured. It moved the needle on boilerplate at the boundaries, on sweeping cross-cutting refactors (find every reference, apply the pattern, flag the exceptions) and on codebase reconnaissance, answering "where does this value get set, and what does that break?" in seconds. The catch: the same tooling that accelerates also produces confident-but-wrong output, so speed depended on a hard, enforced quality gate and on the architecture's boundaries being encoded in tooling.
The workflow I built, not just used
The real leverage came from teaching the tools this codebase. I authored a layer of repo-specific agents and skills that encoded our own conventions, so the AI reviewed against our standards rather than the internet's average:
- Conventions-as-skills. Focused, on-demand skills that each owned one concern: architecture conformance (does this file belong here; does this import cross a boundary it shouldn't), security review organized by request lifecycle (input, auth, authorization, data, exposure), and test trustworthiness (does this test actually fail when the behavior breaks). Each loaded only the relevant rules for the change at hand.
- Specialist reviewer agents. Narrow reviewers with distinct jobs. One verifies a refactor is fully integrated and the old code is actually gone. Another encodes the team's accumulated code-review standards: prefer compile-time safety over runtime checks, settle parallel promises instead of letting one rejection sink the batch, invalidate caches in the right lifecycle hook, use the shared design tokens and UI primitives instead of ad-hoc styling, route through the framework instead of raw navigation, and flag dead code left behind after a change. These got caught automatically before human review even started.
- A local mirror of the CI review. A skill that ran the same review prompt our CI posts on pull requests, locally, so I could see what the pipeline would say before opening the PR, tightening the loop from hours to minutes.
- End-to-end workflow automation. The busywork wired into commands: spin up an isolated branch straight from a ticket (pulling the full ticket context, images included), and open a pull request with a description auto-generated to our template and linked back to the tracker. The path from "ticket assigned" to "PR open" became a few keystrokes.
The point wasn't novelty. It was that every recurring judgment call I made got captured as tooling, so the next contributor (human or AI) made the same call automatically. That compounding is a large part of why the velocity curve bent the way it did. AI didn't replace architectural judgment or the daily conversation with the owners; it compressed the distance between a decision and a working, type-safe implementation of it. The leverage was large on the mechanical majority of the work and roughly zero on the genuinely hard minority, which is exactly where it should be.
How a change moved from ticket to merge
The PR structure was the backbone that made all of this safe at speed. Every change followed the same path, and the shape of it is what kept a fast-moving, multi-engineer codebase from turning into chaos:
- Clear ownership, one branch per ticket. Work was divided so each engineer owned their own area of the code, with the CTO approving, so changes rarely collided by design rather than by mechanism. For my own part I worked each ticket on its own branch in a dedicated worktree, created straight from the tracker with the full ticket context pulled in, a personal choice to keep local changes cleanly isolated.
- Small, single-purpose PRs against a shared staging branch. Pull requests were deliberately small and scoped to one concern, each one demoable in the next daily call. That kept reviews fast, made regressions easy to bisect, and meant work landed continuously rather than in big, risky drops.
- Conventional, domain-scoped commits. Commit messages followed a consistent type-and-scope convention, so the history itself reads as a changelog and the intent of any change is legible months later.
- A hard pre-push gate. Type-check, lint, format, and tests all had to pass locally before a push was allowed. "Works on my machine" stopped being a category of bug, and CI rarely failed on something that should have been caught earlier.
- Templated PR descriptions, linked to the tracker. Every PR opened with a description generated to a shared template and linked back to its ticket, so reviewers always had the what and the why in front of them, and the tracker stayed in sync automatically. The template carried a checklist of replicate-and-verify steps as checkboxes, tied to the affected pages, so a reviewer could reproduce the change and tick off that each case actually worked before approving.
- Automated review before human review. CI ran an automated code review on every PR, and I could run that exact same review locally before opening it, alongside the repo-specific reviewer agents. By the time a human looked, the mechanical issues were already gone and the review could focus on design and intent.
None of these steps is novel on its own. The point is that together they form a pipeline where the boring, error-prone parts are automated and enforced, so the human attention is spent where it actually matters.