| name | improvement-loop |
| description | Run a self-perpetuating, multi-agent improvement loop on ANY codebase (chat, ingest, a UI, infra — anything with tests). A committed backlog of file-disjoint, waved tasks is implemented in parallel by a background Workflow, verified, adversarially reviewed, fixed, committed, and then re-scouted into the next round's backlog. Use when the user wants to iteratively harden/improve a project across many tasks ("improve X", "run a round", "keep iterating on Y", "set up an improvement loop"), to continue an existing loop ("run the next round"), or to fold a fresh ask into the next round. Requires the Workflow tool (multi-agent orchestration). |
Improvement Loop — self-perpetuating multi-agent rounds
A pattern for grinding a codebase forward across dozens of tasks without the human
re-planning each time. One round = implement a wave-structured backlog in
parallel, verify it, adversarially review it, fix what's confirmed, commit, and
scout the next backlog. Saying "run the next round" repeats it. The project
can be anything — the engine is identical; only the per-project context changes.
The engine is a real file: improve-loop.js in this skill's directory. You
run it via the Workflow tool's scriptPath, passing the project specifics as
args. Nothing in the engine is project-biased — it's all in args.
The mental model: two halves
- State — what to do next. A committed backlog file (default
docs/improvement-backlog.json + a human-readable .md). The single source of
truth for the next round. Survives sessions and worktrees because it's in the
repo.
- Engine — how to run a round.
improve-loop.js, stateless; it reads the
backlog from args. The same file serves every project.
The loop perpetuates itself: the last phase of every round is a SCOUT agent
that audits the just-changed tree (and live signals if relevant) and overwrites
the backlog with the next round's tasks. "What to improve next" is always sitting
in the repo, regenerated by the work itself.
Prerequisites
- The
Workflow tool (multi-agent orchestrator). The user must have opted into
multi-agent orchestration (an ultracode session, or they asked to "run a round
/ a workflow"). Don't spin one up for trivial work — see §"When NOT to use".
- The project has a verify command (the engine makes every wave prove itself
green). If it doesn't, the loop is much weaker — flag that.
- The user is OK with the loop committing scoped changes (no PR/push unless
asked).
The backlog contract (the data shape)
[
{
"id": "kebab-case-task-id",
"wave": 1,
"files": ["path/a.ts", "path/a.test.ts", "path/b.py"],
"brief": "Self-contained instructions for ONE zero-context engineer-agent: the problem (with live/code evidence + line numbers), the exact fix, the honesty/contract/style rules, the tests to write first, and the verify command to run."
}
]
What makes it work:
- Waves are file-disjoint parallel groups. Every task in a wave touches a
disjoint set of files from its wave-siblings, so N agents run concurrently in
one working tree without clobbering each other. A task that consumes another's
output (a new contract field, a shared helper) goes in a later wave. This is
the load-bearing rule — get it right or agents collide.
- Group by file footprint, not theme. Two related tasks on the same file must
be sequenced; two unrelated tasks on disjoint files can be parallel.
- Briefs are over-specified. The agent can't ask questions mid-run. Include
paths, evidence, the precise change, the TDD steps, the project's hard rules,
and the verify command.
- One docs task, last wave, alone. It re-runs suites for real counts and
updates docs against the actual diff.
Keep a human .md beside the .json (task list + rationale, priorities, "what
shipped last round", audit findings). The scout writes both in lockstep.
Running a round
- Read the backlog (
docs/<project>/improvement-backlog.json, or wherever the
project keeps it).
- Fold in fresh asks first. New bug/feature since the scout ran? Slot it into
the backlog at the right wave (by file-disjointness) and commit that edit.
Augment task briefs with any live root-cause findings you've gathered — a
brief that names the exact mechanism produces a precise fix.
- Set the claim-work marker if the repo has a claim-work hook (so agents can
edit source):
"$(git rev-parse --show-toplevel)/.claude/hooks/claim-work-marker.sh" set
- Assemble
args.common — the CONTEXT block every agent inherits. This is the
only project-specific authoring per round. Include:
- the repo root and a pointer to the project's CLAUDE.md / handoff docs
- the verify commands (the exact test/typecheck/lint invocations per area)
- the project's hard rules (honesty/contract invariants, TDD, style, the
wire-contract / sync-fence ritual, no-
Any, sentence-case UI — whatever
applies)
- the scope fence (touch only assigned files; no commit/push; the
claim-work bypass line)
- "your final output is structured data for an orchestrator, not prose"
- Launch the engine via the
Workflow tool with scriptPath pointing at this
skill's improve-loop.js and args:
Workflow({
scriptPath: "<this skill dir>/improve-loop.js",
args: {
root: "<absolute worktree path>",
tasks: [ ...the backlog array... ],
common: "<the CONTEXT block from step 4>",
backlogPath: "docs/<project>/improvement-backlog.json" // optional; the scout writes here + the sibling .md
}
})
Pass tasks/args as real JSON values, not stringified blobs. The script's
own dir path is given to you when this skill loads (its base directory).
- Relay, don't babysit. It runs in the background and notifies on completion.
Report waves / suites / confirmed findings / commits / the scout's next-backlog
summary when it lands.
- Rebuild/reload the app if needed (see §"Operational lessons").
The engine ends by committing scoped changes and overwriting the backlog, so the
loop is ready to go again.
Recovery (these are the moves you'll actually need)
- An agent dies on a terminal error (socket drop, API 500): do NOT restart the
round. The other agents are unaffected. Revert that agent's partial edits
first (
git checkout -- <its files> — a half-applied task can leave the tree
broken), then dispatch a standalone agent for just that task with the same
brief.
- Session hits the token limit mid-round: relaunch with
Workflow({ scriptPath: "<...>/improve-loop.js", resumeFromRunId: "<runId>" }).
Completed agents replay from cache for free; only the killed tail re-runs. Same
script + same args ⇒ clean resume. (This is the main reason the engine is a
real file on a stable path, not a copy-pasted template — resume needs the file.)
- If the fixer agent died: its round-2 only carries suite failures, not the
findings list (that was round-1's payload). Diff the confirmed-findings list
against the final tree and sweep any that slipped through with a standalone fix.
Operational lessons
- File-disjoint waves are non-negotiable — the most common failure is two
wave-siblings on the same file. When unsure, push the dependent task later.
- App/artifact refresh after a round: native/compiled changes need a rebuild;
pure interpreted/hot-reloaded changes are picked up live. Know which your project
needs and do it once at the end.
- The adversarial review earns its cost on interaction bugs — defects between
independently-built tasks (a stale sibling; a contract one task changed that
another renders). The find → refute/judge → fix pipeline catches what single-pass
review misses. Scale it: a quick round can drop to one lens + single-vote; a
"thoroughly harden this" round can add lenses, a 3-of-5 vote, and a completeness
critic.
- Honest reporting — relay what actually shipped: real re-run suite counts,
partial/blocked tasks named, the scout's next backlog. If the app/board surfaces
a real problem the round found, say so; the app is the messenger.
Starting a loop from scratch (no backlog yet)
The FIRST step is a scout: spawn one agent (or do it inline) to audit the project
against its goals/docs and write the initial improvement-backlog.{json,md} in the
contract shape, then run a normal round. Seed prompt: "Audit for
correctness gaps, honesty/contract violations, stale docs, sibling defects, and
operational fragility; write a 5–10 task backlog in file-disjoint waves."
When NOT to use
- A single trivial edit, a one-file fix, a quick question — just do it. The
workflow spins up many agents and burns real tokens; it must match the scale.
- The user hasn't opted into multi-agent orchestration and the task doesn't
warrant it — describe what a round would do and its rough cost, and let them ask.
- No verify command exists — the loop's "prove it green" backbone is gone; fix
that first or run a much lighter review.