# Capstone

Course: [Loop Engineering](https://www.devtutorials.ai/learn/loop-engineering) · Section: Loops at Scale
Source: https://www.devtutorials.ai/learn/loop-engineering/loops-at-scale/capstone

> Loop pack for your project, plus export. Build one loop with every part of the course, run it on the full 20-ticket backlog, then export it for Claude Code, Codex or Cursor.

## Loop Pack for Your Project, Plus Export

This is the last lesson. You build one loop that uses everything from the course, run it on the full 20-ticket backlog, and export it for your own tool.

There is no "watch it fail" demo this time. The capstone starts from a loop that has only a trigger and a maker. It fails in almost every way you have seen. Your job is to fix all of them at once.

## TL;DR

- Everyone builds the **goal loop** over the full 20-ticket backlog.
- If you picked a **daily** or **parallel** loop at the start of the course, there is an extra capstone for that too.
- The check runs your loop on 3 versions of the backlog and compares what it did with each ticket's hidden truth.
- A passing loop also has to **export** cleanly for Claude Code, Codex and Cursor.
- For a project you already have, 5 questions fill your real commands into the export.

## A Real-World Example

Think about a driving test.

During lessons, you practised one thing at a time: starting, turning, parking, stopping at lights. The test is one drive that needs all of them. Nobody tells you which skill comes next. You just drive, and the examiner checks how you handled each moment.

Now map this to the capstone:

1. Each lesson was one skill: state, checker, stop rules, triggers, skills, worktrees, connectors, budgets, the inbox.
2. The capstone is the drive: one loop, the whole backlog.
3. The scorecard is the examiner's sheet.

## What You Will Learn

In this lesson, you will learn:

1. How to put all the parts of a loop together.
2. How a loop is graded on the full backlog.
3. How to choose limits that fit the whole job.
4. How to fill in answers for your own project.
5. How to export and start your loop for real.

## The Backlog: 20 Tickets With Hidden Truth

The backlog has 20 tickets. Each has a hidden truth, which the check uses to grade your loop.

```js runnable title="What is in the 20-ticket backlog"
const truths = [
  "fixable", "fixable", "fixable", "fixable", "fixable", "flaky", "fixable", "fixable", "fixable", "done",
  "fixable", "ambiguous", "unsafe", "fixable", "fixable", "fixable", "done", "fixable", "fixable", "fixable",
];
const count = {};
for (const t of truths) count[t] = (count[t] || 0) + 1;
for (const [truth, n] of Object.entries(count)) console.log(truth.padEnd(10) + n);
```

Expected output:

```text
fixable   15
flaky     1
done      2
ambiguous 1
unsafe    1
```

So a good loop must:

- fix and check the 15 fixable tickets (4 of them have a broken first fix);
- send the flaky, the unclear and the unsafe ticket to the inbox;
- skip the 2 tickets that are already done;
- never change anything it should not.

## The Pass Rules

The check grades what your loop **did**, never the text of the loop file.

| Rule | Lesson it comes from |
|---|---|
| Every fixable ticket fixed and checked | Maker vs Checker |
| 0 false "done" | Maker vs Checker |
| 0 repeated work | State |
| #6, #12 and #13 in the inbox | Stop Rules, The Outer Loop |
| 0 unsafe actions | Budgets, The Outer Loop |
| The run ends because its goal is met | Stop Rules |
| The export checks out for every tool | Skills Inside the Loop |

The next box runs the same kind of check on a tiny scorecard.

```js runnable title="Grade a scorecard against the pass rules"
const score = { fixed: 15, fixable: 15, falseDone: 0, repeated: 0, unsafe: 0, inbox: [6, 12, 13], stop: "goal-met" };
const rules = [
  ["all fixable fixed", score.fixed === score.fixable],
  ["0 false done", score.falseDone === 0],
  ["0 repeated", score.repeated === 0],
  ["0 unsafe", score.unsafe === 0],
  ["#6, #12, #13 in inbox", [6, 12, 13].every((id) => score.inbox.includes(id))],
  ["ended on its goal", score.stop === "goal-met"],
];
for (const [name, ok] of rules) console.log((ok ? "pass " : "FAIL ") + name);
```

Expected output:

```text
pass all fixable fixed
pass 0 false done
pass 0 repeated
pass 0 unsafe
pass #6, #12, #13 in inbox
pass ended on its goal
```

## Choosing Limits for the Whole Job

In Lesson 1, 15 turns were plenty. The full backlog needs more. Count it the way you learned in Stop Rules.

```js runnable title="A turn cap for the full backlog"
const fixable = 15;
const brokenFirstFixes = 4; // one extra turn each
const alreadyDone = 2; // one cheap skip each
const escalations = 2; // unclear and unsafe: one turn each
const flakyTries = 3; // same_failure: 3, then escalate
const needed = fixable + brokenFirstFixes + alreadyDone + escalations + flakyTries;
console.log("turns needed: " + needed);
console.log("a safe max_iterations: " + Math.ceil(needed * 1.5));
```

Expected output:

```text
turns needed: 26
a safe max_iterations: 39
```

A cap with some room to spare is safe. A cap of 20 would cut the run off before it finished.

Build the capstone one lesson at a time. Add a part, press **Check my loop**, and read which rule still fails. The hint names the part that is missing. This is exactly how you will grow a loop at work.

```js runnable title="Add one part at a time and watch the failures shrink"
const steps = [
  { added: "trigger + maker only", failing: ["false done", "repeats", "inbox", "unsafe", "stop"] },
  { added: "+ checker", failing: ["repeats", "inbox", "unsafe", "stop"] },
  { added: "+ state", failing: ["inbox", "unsafe", "stop"] },
  { added: "+ stop rules", failing: ["inbox", "unsafe"] },
  { added: "+ escalate and triage skill", failing: [] },
];
for (const s of steps) console.log(s.added.padEnd(30) + (s.failing.length ? "still failing: " + s.failing.join(", ") : "all rules pass"));
```

Expected output:

```text
trigger + maker only          still failing: false done, repeats, inbox, unsafe, stop
+ checker                     still failing: repeats, inbox, unsafe, stop
+ state                       still failing: inbox, unsafe, stop
+ stop rules                  still failing: inbox, unsafe
+ escalate and triage skill   all rules pass
```

This is the order the hints in the lab guide you through. Each part fixes one kind of failure.

## Capstone: A Goal Loop for the Whole Backlog

Everyone does this one.

The starting loop has only a trigger and a maker. Add:

1. A **checker** with a rubric that runs your tests.
2. **Stop rules**: a cap that fits the whole backlog, and `same_failure: 3`.
3. A **state** file.
4. An **escalate** target, and the **triage skill** under `maker:`.
5. **Allowed paths and commands**, so nothing outside them can run.

Then press **Check my loop**.

## Capstone Options: Daily and Parallel

At the start of the course, you picked a loop ambition. If you picked **daily** or **parallel**, do that capstone too. Anyone may try both.

The daily capstone needs a schedule, quiet empty days, and every new CI failure triaged on the day it arrives.

The parallel capstone runs 3 agents on 12 tickets that share files. It needs worktrees, a checker, state, and a review capacity your team can really keep up with.

These two options do not replace the goal loop. Every loop pack in this course starts from a working goal loop. The options show how far the same parts stretch.

## Your Own Project: 5 Questions

The capstone runs on the starter project, so it can be graded. For a project you already have, the **Export** tab asks 5 questions:

1. What is your test command?
2. Where does the work come from (for example, GitHub issues with a label)?
3. What does "done" mean, as a check?
4. How many tokens per day may the loop spend?
5. Where should escalations go?

Your answers are written into `loop.yaml` in the pack. The next box shows the idea.

```js runnable title="Answers filled into the loop"
const loop = { goal: "pnpm test passes for every ticket in this run", escalate: "triage-inbox", rubric: ["run pnpm test", "read the diff"] };
const answers = { testCommand: "npm test", escalateTo: "#team-loop" };

const filled = {
  goal: answers.testCommand + " passes for every ticket in this run",
  escalate: answers.escalateTo,
  rubric: ["run " + answers.testCommand, ...loop.rubric.filter((r) => !r.includes("test"))],
};
console.log(JSON.stringify(filled, null, 2));
```

Expected output:

```text
{
  "goal": "npm test passes for every ticket in this run",
  "escalate": "#team-loop",
  "rubric": [
    "run npm test",
    "read the diff"
  ]
}
```

The answers are not graded. They only shape your pack.

## Export and Start It for Real

1. Pass the goal capstone.
2. Open the **Export** tab, pick your tool, and answer the 5 questions if this is for an existing project.
3. Read each file. Then press **Download**.
4. Follow the checklist in `LOOP-README.md` for the first real run.

The first real run is where a person matters most. Start the loop on 2 or 3 small tickets. Read every diff it makes on the first day. Check every path in the pack against your tool's docs. Only then let it run on more.

## Keep an Eye on It: Loop Health

A loop that passed on day one can drift. Look at a few numbers every week:

| Number | Healthy | If it goes wrong |
|---|---|---|
| False "done" found in review | 0 | Tighten the checker's rubric |
| Escalation rate | Steady, not 0 | 0 can mean the maker stopped escalating |
| Unread changes merged | 0 | Fewer agents, smaller tickets, more reviewers |
| Oldest item in the inbox | Under 2 days | The outer loop is the bottleneck |
| Tokens per fixed ticket | Steady or falling | Look for retries and flaky tests |

```js runnable title="Tokens per fixed ticket, week by week"
const weeks = [
  { tokens: 120000, fixed: 40 },
  { tokens: 130000, fixed: 42 },
  { tokens: 210000, fixed: 35 },
];
weeks.forEach((w, i) => {
  const per = Math.round(w.tokens / w.fixed);
  console.log("week " + (i + 1) + ": " + per.toLocaleString("en-US") + " tokens per fixed ticket" + (per > 4000 ? "  <- look for a flaky test" : ""));
});
```

Expected output:

```text
week 1: 3,000 tokens per fixed ticket
week 2: 3,095 tokens per fixed ticket
week 3: 6,000 tokens per fixed ticket  <- look for a flaky test
```

The **Cheat Sheet** has the full list, an emergency stop and a rollback plan.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| A small cap | "15 turns worked before." | Count the turns the whole job needs. | The run stops before it finishes. |
| No state on a big backlog | "It is one run." | Already-done tickets still need skipping. | Finished work is changed again. |
| No triage skill | "There is an escalate target." | The maker needs the skill to know when. | #12 is guessed and #13 runs on production. |
| A big first run | "It passed the capstone." | Start small and read the evidence. | Comprehension debt on day one. |

## Exercises

Each exercise ends with a value on the last line. Press **Check** to compare it with the expected answer.

## What to Remember

- The capstone puts every part of the course into one loop.
- It is graded on what the loop did to all 20 tickets, on 3 versions.
- Size the limits to the whole job, not to a small exercise.
- The 5 questions fill your real project's answers into the pack.
- Start your first real run small, and read every diff.
- The loop produces evidence. You, the engineer, produce the verdict.

## Further Reading

- [Loop Engineering, by Addy Osmani](https://addyosmani.com/blog/loop-engineering): the full picture this course follows.
- [awesome-harness-engineering, by walkinglabs](https://github.com/walkinglabs/awesome-harness-engineering): loop and harness references for further reading.
- [Effective harnesses for long-running agents, by Anthropic](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents): running agents well over many sessions.

You have finished the Loop Engineering course. Your loop pack is ready to try on your own project.

Next: **Cheat Sheet**, one page with every template, the emergency stop, rollback steps and an index of every lab message.
