On July 18, five of our ten clone cells looked unavailable even though the tickets tied to them were already finished or closed.
That stalled new work before anyone had written a line of code. We run ten parallel clones of the same repository so developers and agent sessions can take separate tickets without grinding on the same checkout. The unit I care about is the clone cell: a checkout, the ticket it is serving, and the branch that may still contain work. At that scale, an abandoned claim is a capacity leak.
A full pool, and two ways to empty it
The pool looked full. The fast fix was to wipe the status board, mark every clone free, and start dispatching again. That recovers apparent capacity immediately, but it treats every old claim as dead. One of the ten cells was carrying an in progress prototype branch, and another feature branch was local only, with nothing on the remote behind it. A blanket clear would have turned a scheduling problem into a recovery problem.
Trusting the existing occupancy marks is the opposite failure. The pool stays safe, and finished work becomes a permanent reservation. Neither approach separates a stale claim from work that merely stopped at a good breakpoint.
So we audited all ten cells against their tickets. The result split into three groups. Five cells were attached to work that was finished or closed. Three were on open tickets. One prototype branch was deliberately parked on its clone. After freeing the five stale or done occupancies, six cells were available for new work.
That count is the evidence the cleanup changed usable capacity. Three active cells, one parked prototype and six open cells account for the full pool of ten.
What the ticket can’t tell you
A closed ticket usually means the application work is complete. It says nothing about whether the checkout holds something that exists only there.
The local only feature branch showed this. Its ticket state made the cell look releasable. Its branch state meant that clearing it without a decision could discard the only copy of unfinished work. The follow up was explicit: push it to the remote if the work needed safeguarding, otherwise leave the audit closed. That is a better question than “is this clone old?”
The sequence we use now:
- Start with the pool, not the session that happens to be noisy.
- Match every clone cell to its current ticket state.
- Separate finished or closed work from open work.
- Check whether an apparently stale cell has a branch that still needs a home.
- Free only the cells whose ticket and branch state agree.
This is deliberately narrower than a universal cleanup command. An automatic age threshold would be tempting, especially when an agent session dies without updating its claim. It would also be wrong for the parked prototype. Time is only a signal.
More clones, more state to go wrong
The early mental model was that more clones meant more parallelism. That is true but incomplete, because more clones also mean more state that can become inaccurate. A clone does not stop being occupied because an agent went quiet. It stops being occupied when we can show that its ticket, branch and intended next action no longer need that cell.
That is why we treat the pool audit as operating work. It took 4 hours and 59 minutes to audit all ten cells and free five of them. It is not glamorous, but it opened six cells for new work without destroying a prototype or losing a local branch.
Ten clones do not give us ten times the throughput by themselves. They give us ten places where a stale claim can hide, and the capacity comes back only when we clear those claims with evidence.
What to check before you free a cell
If you run parallel workspaces for people or agents, audit the pool against ticket state and branch state before freeing anything. A closed ticket does not show that a checkout holds no unique work, so look at whether each stale-looking cell has a branch that needs a home. Free only the cells where both agree.