
Case study · A consumer app company, two engineers
The problem
“On a team of two, nobody has time to be the project manager, so the tickets arrived thin and the board was always out of date.”
Every startup runs on build, measure, learn. The boards most teams use only ever track the build half. I turned the whole loop on the development process itself: cards move themselves from intake to tagged release, and every shipped card comes back with a score for how cleanly it got there and where it first went off track.
Where it started
Bugs and feature requests reached us as Slack messages and forwarded emails, and plenty of them never reached us at all. The ones that did make it onto our board arrived thin. "The map is broken for this person." Which map, on which page, which account, and who was the person? None of it was on the ticket.
So every ticket I picked up opened with a second conversation to recover what the first one left out. That back and forth was what made a small bug tedious and slow. And the tedious ones got skipped: the bug was mentioned in passing, nobody wrote it down, and it came back a month later from somebody else.
Our board already had automations — status rules, ticket templates, required fields. None of them could supply what was actually missing. A required field can force a sentence into a box; it cannot read a screenshot, work out which codebase the broken page belongs to, or ask the one follow-up question that would have made the ticket workable. The gap was never plumbing. It was judgment at the moment of capture.
So the first thing I built was intake: a skill I installed for the whole team through Cowork, so anyone can describe a bug the way they would say it out loud, with whatever screenshots or video they have. It classifies bug or feature, reads the images, asks only for the piece that is genuinely missing, names the card in a consistent format, and files it with the page and the account already attached.
How it grew
I couldn't write a skill from a vague sense of how things go. Deciding what intake hands off meant deciding what triage receives, which meant writing down what triage actually is — and so on down the line. Our process had never been set out as a contract before. Doing it for one stage forced it for all of them.
We already had process documentation, written to bring a new developer up to speed. Read as a specification it was already the right shape: every stage with a beginning, a middle and a hand-off. So I built the rest of the pipeline by following the blueprint that was already there — each stage got a skill that reads its own section of the document rather than restating it. That came with a condition attached: the document has to go on existing, and it has to stay the canonical copy.
The follow-up ticket asked to sync the repository's copy of the document to the copy in the project tool. One rule, two places — the same fragility the old board automations had. I closed it by deleting the second copy: one canonical page, a pointer where the file used to be, a cache so reads are free.
What runs
Each stage says what is already true when it begins, what it does, and what it must leave behind — so the next stage's opening conditions are the previous one's hand-off. Three run as a skill end to end. Three are a person. Two are the two of them in conversation.
Describe the bug or the feature out loud and attach whatever you already have — screenshots, a link to the page, the account it happened on. It comes back as a card with those details and links on it.
Reads the card against all four codebases and tags the one it belongs to. Scores it against the current company goal, with the reasoning for the score written onto the card. Merges duplicates, and links related cards to each other so the halves of a feature travel together.
One of us reads the stack and chooses what goes on deck. The scores are an argument, not an instruction — what gets built next is a human call, and no skill performs this move.
A skill picks an on-deck card back up and explores the codebase in full, read-only: the context around the card, the things likely to get in the way. It drafts a plan. Then the person says how they imagine the solution should look and work, and the two go back and forth until the plan settles. The plan names the tests to write, the specific things a human has to QA by hand, and what gets watched after release. This is where the bulk of the work is done.
Entirely automated. A worktree is created, the implementation is written, and the tests named in the plan are generated and run against it — subagents drive each part. Once it is done and passing, the work is committed to its own branch, stamped with the card's ID, and opened as a pull request that waits on QA.
The card now carries the list from planning: the exact places to test and the things to look at. Green tests are not enough to merge — one of us works that checklist against the real pages first.
The pull request is merged, a new version is tagged with release notes generated from it and shared to the team channel, and the deploy goes out. The card moves to complete — or to measure, if the plan named something to watch. Confirmed per codebase, every time: nothing ships unasked.
A card sent to measure sits until there is something to read, then one of us decides whether the change actually mattered. No skill ages a card onward; this is the learn half, and it stays human.
The human stages are not approvals bolted on for comfort. They are the judgments that set what the work costs: choosing what to build next, attacking the plan before any code exists, and deciding afterward whether the change actually mattered. Planning carries the most weight — a hole missed there is what sends the work back later, which is precisely what the score catches.
And then
At deploy the card comes back with a number out of 100, reduced for every unplanned interruption, every bounce into blocked, every reopen. Cycle time is recorded but kept out of it, so large and small tasks stay comparable. I built it to rate a shipment, and it works better as a diagnosis: the breakdown names the point where the run left the plan — not the last thing that went wrong, the first one.
The thing to be suspicious of is an AI that grades its own tickets. This one starts at 100 and only goes down, and it goes down whenever the system had to stop and ask a human for something it should have known — so it cannot flatter itself without leaving a suspiciously clean record. And nothing on the board is self-reported: every card carries a branch, a pull request, a commit stamped with the card's ID, and a version tag.
Built with
Intake is on demand — anyone, any time, by dictation. Triage and the planning-and-build run are invoked against whatever is sitting in the queue. Merge and deploy run in batches with a confirmation per codebase. Nothing deploys without being asked.
The document we wrote to onboard developers became the thing that runs the process.
This one was a dev board, but the method wasn't specific to engineering: write down what actually happens, mark every step for whether an agent could really do it, then automate the ones that pass. If you have a process running on somebody's memory, I'd like to hear about it.