AI writes code fast. Without a process, it also ships broken work: code that looks right
and isn't, scope that grows without anyone noticing, and a merge nobody checked. Using
coding agents safely seems to need someone watching them all day, and a small team
doesn't have that person.
I had this problem myself. I run a one-person software business and build several
products at once. The same problem faces any team with a backlog and no spare developer
time.
What was built
WASBuilder is a Kanban board where each card is a ticket and each column is a stage of a
fixed lifecycle. Coding agents specify, plan, build, review and stage each ticket. A person
writes the idea, answers the agents' questions and approves the merge. When an agent is
unsure, it stops and asks instead of guessing.
The board, from Idea to Staged. Two cards show an agent at work, with its stage,
its time so far and the last thing it did. This is a demo project with example data.
A person moves itAn agent moves itNeeds a person's approval
Every agent run is recorded: which model ran, at what effort, and for how long. New this
autumn, reports from an application's own users land beside the board, where they are
discussed and turned into tickets.
Result
WASBuilder has built real software. TaskTree, a to-do app that is now in use, was built
through it, and so were this site's recent changes. WASBuilder also builds itself.
Read the TaskTree case study.
These figures are real. They come from WASBuilder's production Stats page for its two
biggest projects, WASBuilder and TaskTree, read when this page was written.
WASBuilder: tickets by type, from production.TaskTree: tickets by type, from production.WASBuilder: lines of code over the last eight weeks.TaskTree: lines of code over the last eight weeks.
Final Review is an independent agent that checks each branch against its specification
before it can ship. Over both projects, for every ticket created since the agents started
(leaving out Tracking tickets, which only group others):
665 of 681 tickets created were deployed to production
16.8% of those were sent back by Final Review before they could ship
17.4% needed any rework at all, counting review, a person sending them back and a
failed staging deploy
249 lines changed in the median ticket
The honest limits: a person still writes the ideas and approves the merges. Agents still
get things wrong, which is why Final Review sends some tickets back, and why the human gate
stays.
Effort and cost
All of this is a side project. One person directs it in evenings and weekends, around
client work, while the agents run whenever there is a ticket ready. In the seven weeks since the
agents took over, they have written 795 of the repository's 1,127 commits, over 282 tickets.
Every agent run's time is recorded, by the coding agent that ran it, and chat turns are recorded
separately.
WASBuilder: agent runs and time, by coding agent.TaskTree: agent runs and time, by coding agent.WASBuilder: conversations over the board.TaskTree: conversations over the board.
"No agent" runs are the deterministic steps: syncing a branch, merging and deploying. They
are git and shell, and no model is involved. All of these figures are from production.
What a small team would have needed
How does a side project, run in evenings and weekends, compare with hiring? Below is the
work done in seven weeks on WASBuilder and three on TaskTree, set against a full-time team of one
senior and two junior developers, against what the agents' work would cost at published API
prices, and against what was actually paid. Each figure says what kind of number it is.
WASBuilder
TaskTree
Both
What was built (measured)
Product code added, in lines (not counting blanks and comments)
27,548
40,888
68,436
Test code added, in lines
38,810
26,952
65,762
Calendar time, part-time
7 weeks
3 weeks
7 weeks
A small team (a very rough estimate)
Effort, in person-months
35 to 110
51 to 170
86 to 290
Calendar months for three people, full-time
12 to 38
17 to 58
29 to 96
Salaries with benefits, CAD
310,000 to 1.6 million
460,000 to 2.5 million
780,000 to 4.1 million
Salaries with benefits, USD
420,000 to 2.2 million
620,000 to 3.4 million
1.0 to 5.6 million
The agents' tokens at published API prices (a floor)
USD, at least
1,600
2,100
3,700
What was actually paid (fact)
Claude Max and ChatGPT Plus, three months, USD
360
The team estimate counts only the product code written in the period, not the tests, and the
two methods behind it disagree by a factor of three, so it is shown as a range. Read it as an
order of magnitude, not a quote. Even its low end is more than two years of full-time work for
three people, against seven weeks of one person's evenings and weekends. The subscriptions also
paid for other work in those months, including HARchive and this site, so USD 360 overstates
what these two projects cost. Other running costs, such as the server WASBuilder runs on, are
left out, because a team would have them too.
How we estimated this
We asked what a small team of one senior and two junior developers would have needed to build
the same work. We counted only the code written in the weeks measured, not code that already
existed, and left out the tests, documentation and shared libraries. We then
sized the effort two ways. COCOMO II
is a published model from the University of Southern California, used here with every setting
at its default. The other method uses industry productivity averages from
Capers Jones,
after converting lines of code to function points with
QSM's published ratios.
A team's calendar months are its effort divided by three people working full time.
For pay, the senior is paid between the median and the top tenth, and each junior between the
bottom tenth and the median, from government wage data:
Canada's Job Bank
and the US Bureau of Labor Statistics.
Benefits are added using the BLS
employer cost survey, where wages are
69.2% of what a professional costs an employer. Office space, equipment and management are not
included, so this understates a team's full cost.
The token figure prices each of the 4,250 agent runs in the period at the vendors' published
rates (Anthropic,
OpenAI). Where the share of cached
input was not recorded, it is priced at the cheaper cached rate, and the few runs that recorded
nothing count as zero, so the figure is a floor.
How it works
The rest of this page is the technical tour. Apart from the Stats screenshots above, which
are production, the screenshots and recordings below come from a demo project seeded with
example data. The recordings drive the real server and the real pages. The agent runs in them
are scripted, so a stage that would take ten minutes takes two seconds.
Nobody touches the page. The board redraws whenever an agent reports: the
progress lines change, and three tickets move a column as their stages finish.
How a ticket moves
The lifecycle is deliberately rigid. A language model is like a person: if you push it too
hard for too long, it goes off the rails. So the work is broken into short stages, each with
a fresh context, one job and one artifact.
Specify. The agent reads the idea and the code, grades the change, and writes a
specification. If anything is unclear, it asks first and writes nothing.
Plan. A plan, a task list, acceptance criteria and a test plan. A plan that needs
more than ten tasks may be split into more tickets before any code is written.
Implement. A loop: sync with main, work through the open tasks, run the checks,
commit and push, and go round again until the tasks are done.
Final Review. A separate run checks the branch against the specification. Major
defects become tasks and send the ticket back to Implement.
Stage. The branch is merged with every other reviewed branch and deployed to
staging, unattended.
Merge and deploy. The one human gate. Production is a blue/green deploy with a
health check that compares the running commit with the one that was built.
Cards can be dragged between columns, but the server decides what is legal. An illegal drag
snaps back and says why.
Idea to Backlog is a person's call, and is allowed. Backlog straight to
Implemented skips three stages, and the board says which moves are open instead.
Every ticket is a record
Everything an agent produces lands on the ticket, in plain text a person can edit: the
specification, the plan, the acceptance criteria and the test plan, then the tasks, defects,
questions and notes. Editing the brief marks what was written from it as stale, so nothing
downstream quietly works from an old version.
A ticket the agents have taken from a two-sentence idea to Reviewed.
Each stage is one run of a coding agent. The run records which model ran, at what effort and
for how long. Its transcript is kept as a log, and the review report becomes a note on the
ticket. Three rounds in a row that change nothing is a stall, and a stall is a question for a
person rather than a fourth round.
The review report, the notes and the five runs behind one ticket, each with its
model, effort and duration.
Where the agents stop and ask
The rule is to make everything as deterministic as possible, and to escalate the rest. An
agent that can't decide something from the code or the documentation asks a question on the
ticket and stops. A merge conflict, a task list that has outgrown its budget or a failed
health check does the same. Each one raises an alert, in the bell on every page, by email or
by text, as each project's rules say.
A run stops to ask, and its alert arrives in the panel while it is open. One click
goes to the question.
Answering the question releases the ticket, and the next stage carries on from where the
agent left off.
The question is answered, the ticket goes from Waiting to Idle, and the Plan stage
picks it up.
Not every stop is the ticket's fault. When a coding agent's subscription hits its usage
limit, WASBuilder pauses that agent across the fleet until the reset time and raises one
alert, instead of letting every ticket in the queue fail on the same limit.
A conversation over the board
The chat panel opens a conversation about the project, answered by an agent with the
repository checked out. It knows every open ticket, so you can ask what is left before
something can ship, or why a build failed. A screenshot can go with the question, and each
conversation picks its own coding agent, model size and effort.
A new conversation with a screenshot attached, and its coding agent, model size
and effort chosen before it is sent.
It can also file tickets, and edit the ones that are still ideas. One turn can file several
tickets with their parent and blocking relationships in place. They appear on the board behind
the panel, and each one links back to the conversation it came from.
One turn files a bug with its parent and blocker set, and rewords an Idea ticket.
Both changes reach the board behind the panel.
Feedback from your users
An application built with WASBuilder can collect feedback from its own users, with the page
they were on and a screenshot. Reports from production and from staging land on one page
beside the board. Each one can be dismissed, discussed with the chat agent, or filed as a
ticket, and the decision is kept with its reason.
Reports from production and staging, each with the view and version it came from,
and a screenshot where the user sent one.A report sent from inside TaskTree is discussed, the agent files it as a feature,
and the feature is on TaskTree's board.
Feedback is read through the same careful door as everything else from production. An
application lists the tables it is willing to expose, and WASBuilder proxies read-only
requests for them with a token the agent never sees. A field the application hides from its
own users is hidden here too.
The fleet
WASBuilder owns the data and enforces the state machine, but it never runs a coding agent
itself. A small fleet of programs polls it for work: a coordinator on each machine takes a
lease on the next ticket, a short-lived virtual developer drives the coding agent for one run,
and a deploy manager takes the staging and production deploys. They run in WSL, on a VPS, and
natively on Windows.
The fleet, managed from one page. One machine's Codex has been signed out and is
waiting on a device code.
Isolation is the real boundary. A virtual developer has no access to the host's files, a git
credential that can't push to main, and branch protection on the server to back that up. A
coding agent is given a shell, which is trust rather than a sandbox, so the environment is
what makes it safe. Every write an agent makes is attributed to its own service account.
Which model, for which stage
Each stage is set up with a coding agent, a model size and an effort level. Specify and Plan
get a large model thinking hard, because a mistake there is repeated by every stage after it.
Implement can run on something faster.
The coding agent, size and effort for each stage, and which model each size means
for each coding agent.
Claude Code, Codex and Copilot are interchangeable for any stage. The choice travels with the
work order, so what the settings page says and what the run uses can't disagree.
Built to be run from a phone
Most of what a person does in this system is read a question and answer it, or read a
review and approve a merge. That happens wherever you are, so every page works on a phone,
and the alerts can reach you there.
The whole thing is Go, with a plain HTML, CSS and JavaScript frontend: no build step and no
framework beyond a small one of my own. The browser tests drive a real headless Chrome
against the real server, and a run of the checker is the gate for every change, including
the agents' changes. The recordings on this page were made with that same harness.
What I learned building it
Ask first, write second. A stage that asks a question and also writes its artifact
against a guess produces an artifact nobody revisits. The answer always arrives too late to
matter.
Short runs, fresh context. One stage per run keeps the model sharp, and a crash
loses one stage rather than a day of work.
Make the boring parts deterministic. Syncing a branch, merging, building staging
and deploying are git and shell, not judgment. None of them uses a model.
The server decides what is legal. Every result an agent sends back is checked on
the server. The state machine is the only description of what a ticket may do.
Know whose problem it is. A usage limit belongs to the account, and an expired
sign-in belongs to the machine. Neither should show up as a failed ticket.
Could this work for you?
WASBuilder follows my process: my stages, my review rules, and the points where I want to
be asked. Every team builds software a little differently, and the tool should fit your
process rather than the other way round. I can build you something similar, shaped to how
your team already works.
The short answer, and what it would take on your own codebase, is on its own page.