How to Use This Course
The two chapter types
Every arc alternates between two kinds of chapter, and they ask different things of you.
Concept chapters are the lecture. Read them without touching the keyboard. They argue why before how, they carry small runnable examples in a toy domain that mirrors the real build one-for-one, and they end with a short list of questions you should be able to answer for yourself. If any are fuzzy, that is the signal to stop and re-read before moving to the build. Do not proceed to a build chapter on a shaky concept; the whole point of frontloading concepts is that the build then feels obvious.
Build chapters are the pair-programming session. Here you write the code, test-first, in the same loop every time:
- Write the failing test. You write it, from the behavior we described — not by copying an answer.
- Predict the failure. Say out loud (or note down) what the compiler or test runner will report.
- Run it and check your prediction. The gap between prediction and reality is the lesson.
- Write the minimal implementation. Just enough to make the test pass. No more.
- Run again, watch it pass.
- Commit.
serde and derive macros; traits, generics, and trait-object seams; async/await and tokio basics; mock-server testing with wiremock; clap; and the thiserror/anyhow error split. We do not re-teach these. What is new here — services, persistence, scheduling, and networking — gets a concept chapter of its own before you build it.
The predict-then-run loop
The prediction step is not a ritual; it is the mechanism. When you guess what cargo test will print — which test fails, on which line, with what left-and-right values, or which E-code the compiler will raise — you commit to a model of how the code behaves. Running it then either confirms that model or corrects it, and a corrected model sticks far better than one you were simply handed. In the networking and persistence arcs especially, the failures are new (a dropped connection surfacing as a retryable error, two schedulers racing for the same run), so the predict step is where those new failure modes become intuition.
Running the tests
The project is a Cargo workspace — one repository, several crates. That means you can test one crate in isolation or the whole thing at once:
cargo test -p control-core # just the crate you are working in
cargo test # the whole workspace
Working on one arc, you will almost always want the -p form: it is faster and its output is scoped to the crate you are editing. Run the full cargo test before you commit, to confirm you have not broken a downstream crate that depends on the one you changed.
No arc needs a running database, a live model API, or a second machine. Every test runs from a plain cargo test — the persistence arc uses an in-memory SQLite database, the eval arc uses a mock HTTP server, and the cluster arc opens a real socket on the loopback interface. The next chapter explains that stance in full.
The concept-check quizzes
Each arc ends with one graded quiz. These are not busywork — they target the exact misconceptions that cause bugs three chapters later. Some questions are Tracing questions: a short program, and you decide whether it compiles and what it prints. Those programs are compiled by the real rustc when the book is built, so the answer is not a matter of opinion. Answer honestly before revealing; a wrong answer with a good explanation teaches more than a lucky guess. The score is for you, not for anyone else.
The answer key
There is a companion implementation plan (linked in the appendix) that contains the full, worked version of every task. Use it as an answer key, not a script. Try each build yourself first. Check the plan after. The distance between your version and the plan's version is precisely where the learning lives — if they match, you understood it; if they differ, the difference is worth investigating.
Working setup
You will want two things open side by side: this book, and a terminal in your project directory. A split screen or two monitors. The loop is fast — write test, run, read error, fix — and it only works if the feedback is immediate.
When you get stuck
Bring the exact error message, verbatim. Rust's compiler errors are unusually good; most of the time the fix is in the error itself, and learning to read them is half of learning the language. When we work through a stuck point together, we dig into what the compiler is actually objecting to rather than papering over it.