Run craft mode for real. Free and written.
Run craft mode for real against the supplied starter-repo task: trace the Worker and Queue by hand, predict what your junior engineer will find, review its plan with the two interrogation questions, push back where warranted, and confirm the memory loop actually ran.
This is the written Lab 1 from Course 0. The recorded walk-through is inside Course 0.
The lab runs on course0-supplement, a small practice repo with zero runtime dependencies (Python 3.9 or later).
git clone https://github.com/kayashaolu/course0-supplement.git
cd course0-supplement
python3 -m unittest discover -s test -t .
This is course0-supplement, the small practice repo both labs in this course run on. This starter repo is Python, one track, nothing to pick. It ships small on purpose: small enough that you can read the whole thing before your junior engineer ever touches it.
Clone it now if you haven't:
git clone https://github.com/kayashaolu/course0-supplement.git
cd course0-supplement
Two folders carry the real work. src holds worker.py and queue.py, the code you are about to change. test holds the test suite, green on a fresh clone, before you have touched anything. pyproject.toml states the floor this code runs on. README.md is the source of truth if anything about the shape of the repo is unclear.
There is no pip install step. This repo has zero runtime dependencies, so there is nothing to fetch and nothing that can drift between when it was written and when you cloned it. One command proves the green state for yourself, run from the repo root:
python3 -m unittest discover -s test -t .
Run it now if you have not already. That confirms the floor you are building on before you read a single line.
Type /scaffold now, before you read a single line of code yourself. It is installed from the Course Overview; if you skipped that, do it there first.
On its first run in this repo, before it even looks at the task, it asks you something: "Want a few minutes to explore this codebase yourself first, read-only, before we start? No wrong answer." Saying no, or staying silent, is a completely fine answer too: scaffold just moves on and sets up its own running record of what it learned, no penalty either way. Here, though, say yes. This is the moment that invitation exists for.
Do your read inside that exploration. In the src folder, open two files: worker.py and queue.py. They are short on purpose. Read them with one question in mind: what does drain() do today, when process(job) throws?
Trace it by hand. drain() pulls jobs off the queue one at a time and hands each one to process(). Follow the path where process(job) throws: where does that job end up, and what happens to the jobs still waiting behind it? The answer is in the code, stated plainly. Do not move on until you can say it in one sentence.
If a line does not parse, ask Claude Code to explain that line, inside this same exploration. That is the right use of the AI here: a tool for understanding how this flow works, not a stand-in for your understanding of it.
Put one real question to it, not a request for a paraphrase. "Explain this repo to me" produces an answer you cannot check against anything. A better question is checkable: it points at a specific fact in the code and asks for a specific answer you can confirm yourself.
Two examples, both answerable from this repo's src folder. A lifecycle question: "Trace one job from queue.enqueue in cli.py through drain()'s while loop. Which list does it land in, and what's the very next thing that happens to it after that?" A what-breaks-if-removed question: "Imagine the try/except in drain() is gone. What's the first job whose failure would end the entire run?"
Check the agent's answer against the lines yourself. Do not take it on faith: the point of asking is to test your own read against a second one, not to replace your read with the agent's.
This exploration is your own pass, and it happens before scaffold ever turns to the task. What comes next is a separate thing: your junior engineer reads this same code itself, to build its own plan. Two reads, two different purposes; the next section covers the second one.
You are minutes away from being asked what you think, and then from judging a plan that changes this exact behavior. Both go better when your answer comes from code you have read, not from a cold guess, and not from memory of the previous lesson's demo.
Hold on to your one-sentence answer. It is about to matter twice: once when your junior engineer asks you to predict, and once when you read its plan.
This lab's task does not live in this repo. There is no tasks folder to point at. You bring the task in yourself, as the opening message.
Type /scaffold again yourself (it is not part of the block), then paste the block below into that same message, after the command, before you send. The block is the retry task's complete text, unedited, and it is the only thing you copy. One message goes out: the typed command plus the pasted task.
# Task 1: retry-with-backoff for failed jobs
## Context
The Worker treats a failing job as gone: `process(job)` raises, the job
lands in `failed`, and nothing happens to it again. Real workers usually
give a job more than one chance before giving up.
## What to build
Give the Worker a retry policy: when a job fails, try it again a bounded
number of times before finally reporting it failed, with a wait between
attempts that grows longer each time. You decide the policy, the numbers,
and where they live.
## Done criteria
1. A job that fails a few times and then succeeds ends up `succeeded`, not
`failed`.
2. A job that keeps failing ends up in `failed` exactly once, with its
attempt count discoverable afterward.
3. The existing tests in `test/` still pass, except the baseline no-retry
assertion at `test/test_worker.py:41`
(`self.assertEqual(calls["count"], 2)`) -- retry changes that count, so
update it and say why.
## Not specified: your call, with a reason
The task doesn't say what the Worker does with the rest of the queue while
one job is retrying. Pick a behavior and write down why. Be ready to
explain the tradeoff to a reviewer.
## Out of scope
The dead-letter path -- what happens to a job that exhausts every retry --
is Lab 2's task.
That is the whole invocation. What happens next is not code appearing immediately. Your junior engineer reads what you pasted and the surrounding code first, so it understands what it is looking at. Only then does it turn to you, and it does not turn to you with an answer.
It turns to you with a question. The previous lesson told you this moment was coming: before your junior engineer shows you any of its own analysis, it asks for your honest first read of the code. This is deliberate: it wants your read, not your agreement with its conclusions. And you have made this easier on yourself already: you have read the worker and the queue, so your first answer does not have to be a guess.
"I don't know yet" is a real, costless answer, the first time you are asked. You are not being scored on this. If you genuinely do not know enough to have a view, say exactly that. Your junior engineer will walk you through what it found, and the plan conversation continues from there.
Whichever way that first question goes, one rule covers everything that follows. You heard it in the previous lesson, and your junior engineer will state a version of it to you directly in its own opening turn: you go back and forth on the plan until you both agree, and nothing gets built until you approve it. Predict, or say you do not know yet. Review the plan it proposes. Push if something is missing. Approve only once you actually agree.
When the plan arrives, run the two questions from the previous lesson:
If these feel familiar, they should: they are the same two questions you watched catch a flaw in the previous lesson's worked example. That is exactly why the next part matters. Check your reasoning against the code in front of you, not against your memory of that demo. That lesson's answer belonged to that lesson's example; this plan is yours to judge.
On this task specifically, the second question is the load-bearing one: does a job that is retrying hold up every job behind it in the queue, or does the queue keep moving around it? You traced what today's code does when a job fails. What this plan decides to do instead, and whether it says so at all, is what you are reading for. If the plan states an answer with a reason grounded in the actual code, that is a plan you can approve. If it is silent on the point, that silence is your cue to ask, not to assume it does not matter.
If the plan holds up under those two questions, approve it and let the build run. If it does not, push back, specifically, on the point that is actually missing. That exchange, not the code that follows, is the rep this lab is built to give you.
Once the build finishes, check two things yourself rather than trusting the test suite alone:
scaffold-wiki folder should now exist in your repo, and it should contain a fresh entry describing what your junior engineer just learned building this task. This course calls this memory the wiki: a running record of what your junior engineer learned and decided; for this lab, confirming the entry exists is the checkpoint.This lab produces two deliverables, and only one of them is your junior engineer's own work:
learner/. This is its record of what you demonstrated, not your own account of the judgment you exercised. It is separate from the codebase/ notes it keeps elsewhere in the same wiki.If the plan held up cleanly on your first read with nothing worth pushing on, say so honestly in your note. Not every round needs a fight. What this lab checks is whether you actually looked, because that is the rep the previous lesson said you would need, finally happening.
Course 0 is the full version of this lab: eight lessons, two labs and three challenges, all self-paced.