Small experiments first
The first experiments were small, almost administrative. I turned on CodeRabbit on GitHub and let it run an automatic pass on every pull request, a private check before the review my team actually trusted: the synchronous kind, in pair, sitting next to whoever had written the change. The insights were often worth reading, though the nitpicking wore thin after a few weeks.
Bugfixing asked more of me. Instead of flipping a switch on someone else's tool, I built a small n8n workflow that watched for a bug landing as a GitHub issue and went looking for likely causes before anyone opened the code.
Then Cursor shipped its own automatic workflows for the same job, code that could look at an open issue and act with less scaffolding than I'd needed to wire together myself. I pointed those at the same issues n8n had been watching.
None of it composed into anything you could call a system. Each tool did one job, in its own corner, and I moved on once it had answered the question I'd asked it.
A repo that looked like mine, and wasn't
I cloned nWave on a Sunday afternoon, half expecting it to make my plans redundant. One of its creators, Alessandro Di Gioia, co-wrote Agile Technical Practices Distilled, a book that changed how I thought about my career. Andrea Laforgia, someone I follow and trust, used it and vouched for it publicly. The instinct behind nWave looked close to mine: bring product thinking and best practice into an agent's skill set at the same width I try to bring to a team, not just technical purity.
I ran a first experiment, and it was interesting enough, but it didn't click. Part of that was context: the codebase I tried it on was legacy enough, and constrained enough, that it was hard to give the experiment room to prove much either way. The rest was something I couldn't quite name at the time, a mismatch I only understood later, once I'd built my own version and could compare the two side by side. So I decided to build a set of skills myself, from the ground up, tuned to how I work.
What fourteen years of notes bought me
What made that decision cheap was an archive I already had. Since 2012 I've kept notes on XP, TDD, continuous integration, Lean, DevOps, technical excellence in general, and I'd recently moved that archive out of a plain notes app into Recall, a knowledge base built for exactly this kind of retrieval. Fourteen years of studied, tested opinion doesn't turn into good agent instructions by itself, but it collapses the distance between "I have an idea for a skill" and "I have a skill with real judgment baked into it." The first version of the repo, xp-developer-skills, already had teeth, because the material behind it wasn't new.
I named the framework AMPD: Amplified Extreme Programming and Product Development, which is exactly what I was after: the practices I already trusted, made bigger. It was also the first time I was doing agentic programming for real, past the small, contained experiments that came before it. I started with the part of the day I actually spend writing and shipping software, and imagined one skill per action I take on a normal day: a bugfix skill enforcing red before green and a minimal diff, a legacy-testing skill built around Michael Feathers' idea that untested code is legacy code by definition, finding seams, adding characterization tests, then refactoring once there's a safety net under it. A spike skill for the moments where the real question is feasibility, not correctness: time-boxed, disposable, judged against one goal instead of the usual bar. A refactoring skill. TDD and ATDD skills underneath all of them.
Eight or nine well-made skills sitting in a folder are still a toolbox. Nothing connected one skill's output to another skill's input, so each one ran in isolation, judged and closed on its own terms.
The unit, not the skill
The shift came while building two skills meant to work together from the start: new-feature and new-increment. I'd wanted to bring continuous integration and incremental product delivery into the framework from day one, and the idea behind them is simple to state. Take a feature, cut it into increments. An increment, in my definition, is a slice that's releasable to production, not necessarily a slice a user can see or touch. A finished backend endpoint that nothing calls yet is still an increment: it's done, tested, deployable, and it happens to be invisible until a later slice wires a frontend to it.
That definition is what made composition possible, more than any single skill did. Once "increment" meant the same specific thing to a planning skill and to an implementation skill, one could hand work to the other across a boundary that held. The realization that mattered was about the unit, not the skill: the thing two skills agree on is what turns a pile of capabilities into something closer to an operating model.
new-feature and new-increment
new-feature's job is planning, and nothing else. It never touches source or test files. Given a feature, it writes an ordered backlog of increment lines to a file, confirms that plan with me before anything gets built, then hands off one open line at a time. new-increment's job is delivery: take exactly one line, apply strict TDD by default against a shared test list for the feature (not one file per increment, one file, one section per slice), reach for acceptance-level testing only where a real outer seam exists, an API, a UI, a contract. At the end, every verification step the project defines has to be green: tests, lint, types, whatever else is configured. Then it squashes its work into a single commit and stops.
That last part, the stopping, is the part that matters most and is easiest to undervalue. new-increment is not allowed to reach for the next backlog line on its own, even when I've told new-feature to run the whole backlog without stopping between slices. That decision belongs one level up. The constraint of one increment per invocation is what makes agent-produced work checkable at all: a slice small enough to hold in your head in full, revertable with a single command if it's wrong, verified against a test list that existed before the implementation did rather than one written to match it afterward.
The rest of the toolkit
new-feature and new-increment weren't the only skills in the folder. Once the unit clicked, the rest of the toolkit stopped being a pile of separate tools and started picking up defined roles inside the same loop.
increment-review is the one new-feature calls by default after every new-increment run. It's fast on purpose: read the mini-journal, read the diff for that one commit, and pick one of three verdicts inside about a minute. Approved moves the backlog forward. Changes-requested comes with a short fix brief, two to six lines, handed straight to refactoring, since a design or test-gap issue is a refactor-hat problem, not a new feature. Bug-found means the code is actually wrong, not just untidy, and that gets routed to bugfix instead, because refactoring is only allowed to touch structure, never behavior.
Legacy-testing and refactoring got a defined sequence too, wrapped into a subagent called legacy-refactor: harness first if there's no trusted safety net for the code you're about to touch, then, only once that net is green, the structural changes, small mechanical steps, tests re-run after each one. New behavior stops the whole thing and hands off to new-increment. The order matters more than either skill on its own does. Skipping the harness step and refactoring straight into legacy code is exactly the mistake Feathers' method exists to prevent.
Tweak is the smallest piece, and the one I reach for the most on a given day: a color, a copy change, a small logic fix that doesn't need a backlog file or its own branch. One commit, scoped tests, scoped lint, done. It exists specifically so I'm not tempted to make an untested direct edit "because it's just a small thing."
pr-reviewer sits above all of it, at the point where a PR is about to merge rather than an increment about to land. It's more skeptical and slower than increment-review on purpose: hat discipline (did a refactor sneak in a feature), increment scope (does this PR actually match one increment, not the whole backlog at once), test strategy against what the project defines, Object Calisthenics on any OO the diff touches. Where increment-review is a fast checkpoint inside the loop, pr-reviewer is the gate at the door.
All of it held together on paper, in the small tests I ran against it while building it. What happened once I stopped reading every diff by hand, and once the whole loop had to survive a real, messy project instead of a kata sized to make it look good, is where the story picks up next.


