The working loop

Predict, Write, Specify, Delegate, Audit, Defend

The agent can write the code. Only you can own it. To own a piece of C or C++ means to predict what it does to memory before it runs, explain it line by line afterward, and prove it with instruments.

  1. 1

    Predict

    You, no AI

    A written prediction: output, memory state, operation count, and how sure you are.

  2. 2

    Write

    You, no AI

    One small piece by hand, to build the mental model.

  3. 3

    Specify

    You

    The interface, unit tests, complexity budget and ownership rules. In the Tutor phase: the question you will ask.

  4. 4

    Delegate

    The agent

    The implementation from your spec, or an explanation in the Tutor phase. Prompts and transcript saved.

  5. 5

    Audit

    You and the tools

    The Audit Report: tests, sanitizer and Valgrind output, your own cost derivation against a timing plot, defects, keep or rewrite.

  6. 6

    Defend

    You, live

    A five-minute oral: why this bound, what input breaks it, where this memory is freed.

Never delegated, in any phase

Your first prediction · your first debugging hypothesis · the ownership and lifetime section of a spec · the final judgment that code is correct · the memory checkpoint

The loop. Every piece of work follows the same six steps, the working loop: Predict, Write, Specify, Delegate, Audit, Defend. You predict on paper what code will do, write a small piece by hand, specify what you want from the agent, let the agent do its part, audit the result with instruments (warnings, sanitizers, Valgrind, gdb, tests, timing runs), and defend your conclusion aloud. Chapter 2 teaches the loop in full, along with the stance behind it, verified constructivism: you build your own model of the machine, and you believe an agent only when the evidence agrees.

Five things are never handed to an agent: your first prediction, your first debugging hypothesis, the ownership and lifetime section of a specification, the final judgment that code is correct, and the memory checkpoint.

The phases. What the agent may do grows in three phases.

In every phase, three parts of each chapter stay AI-free: the hand-worked concept section, the prediction exercise and the memory checkpoint.

The Audit Report. From the first programming assignment (Chapter 5) on, every assignment ends in an Audit Report of one to two pages in seven parts: specification, agent log, correctness evidence, memory-safety evidence, complexity analysis, defects found, and your decision to keep, rewrite or partly rewrite. Appendix A has the template and a filled example. Most of an assignment's grade comes from this report.

The work log. From Chapter 2 you keep a work log, one row per session (Appendix E). Before the session you write your estimated hours; before you ask anyone, your prediction and how sure you are ("I was 70% sure"). Afterward you record the result, the defects found and the instrument that found each. Each assignment ends with a calibration line: average confidence against hit rate. Chapter 19 uses it to compare estimates with actual hours.

The memory checkpoint. Every chapter ends with five questions answered on paper, agent and notes closed: a diagram, a prediction, a bug to find, terms to define. Concept and vocabulary are scored separately, and the answers are with your instructor. If you miss a question, reread that chapter's N.1 and N.2 before moving on.

The oral defense. Each assignment is followed by a five-minute conversation, usually with a teaching assistant, about your code. Three questions recur: Why does it cost what you say? What input breaks it? Where is this memory freed? A line you cannot explain counts as a line you did not write.

Reading order. In week 1, read Chapters 1 and 2 and work through Setting Up Your Workbench before your first lab. Then read the chapters in order; each builds on the memory model of the one before. Read every N.1 with a terminal open and run every listing. When the text says "Write your prediction before reading on," cover the page and do it. Chapter 20 (concurrency) is optional.

The three phases

PhaseChaptersWhat the agent may doRoles
Tutor1 to 9Explains concepts and compiler messages, quizzes you and makes practice problems. It writes no code you submit.Tutor, Drill maker, Confused peer
Pair10 to 15Writes small units from a specification you wrote first. You audit every line.adds Pair and Adversary
Team16 to 20Several agent sessions in separate roles. You direct them and make the final call.Writer, Reviewer, Tester

Evidence and testimony

Chapter 2 sorts every claim you meet by where it comes from. Instruments give evidence. The agent gives testimony, which can be right and is often useful, but has to be checked. The figures for agent accuracy come from one study of a first-year C course (Taylor et al. 2024), so treat them as rough.

SourceKind of claimHow reliableHow you check it
Compiler errors and warningsEvidenceVery reliable that something is wrong; warnings have incomplete coverageTreat warnings as errors; read the first error first
Sanitizers, ValgrindEvidenceFew false positives; silent on paths a run never reachesRun on every build; add inputs that reach more paths
TestsEvidenceOnly as good as the cases; a pass proves less than a failureWrite edge cases first
DebuggerObservationShows what is, not whyCompare with your own memory diagram
The agent on compile errorsTestimonyOften right (about 90% in one study)Accept provisionally; confirm with a rebuild
The agent on runtime and memory errorsTestimonyMuch weaker (about 75%), and as confident when wrongNever accept without a sanitizer run and a hand trace
The agent on undefined behaviorTestimonyLeast reliable; often describes what one compiler happened to doCheck a reference; run UBSan
Your own predictionConjectureStarts weak and should improveCompare with every run; log hits and misses

Chapter 2 also names the stance behind the loop, verified constructivism: you build your own model of the machine, and you treat the agent's output as testimony that instruments must confirm.

The loop in every chapter

Each chapter ends by saying what each step looks like for its topic. Pick a step to read it down the whole book.

ChPredictWriteSpecifyDelegateAuditDefend
1each line's output, and any line with undefined behavior, before compiling.the corrected version by hand, with no casts used to silence warnings.one question for the tutor about the result you still cannot explain, with your guess.the tutor explains under the tutor prompt; it writes no code you keep.check the explanation with a UBSan build and rebuilds at -O0 and -O2.explain the result to a partner in one minute, naming the rule and the instrument.
2you write the output of Listing 2.4, your confidence and a time estimate.the instructor writes a short function by hand; you write your fix to Listing 2.4.the instructor, then you, write a question for the tutor with a hypothesis.the tutor explains; it writes no code anyone submits.the instructor checks the tutor's claims with a rebuild, a sanitizer and a test; you check the claims about Listing 2.4.you answer one Defend it question aloud in under two minutes.
3counts for the three lab loops, as formulas and for n = 7, with confidence.a recursive function by hand: stn_factorial (or a recursive helper for stn_ipow), overflow check first, with its stack drawing. You may submit a loop version instead (Section 3.1.9). PA1 begins.a tutor question about one wrong count: your prediction, the counter's result, your explanation.the tutor explains with questions and hints; no code.the counter, a gdb backtrace at the deepest call, and the sanitizer build on Table 3.5.explain the count formula to the TA in two minutes.
4ten predict-the-output items on paper, with confidences.swap and a function with two out-parameters (stn_mean_sd for PA1), by hand.a question to the tutor about one wrong prediction, with the run that refuted it.the tutor explains as numbered claims and writes no code you submit.a gdb memory dump (p, x/4dw) checks each claim; a known-answer test checks your functions.teach the confused peer that sizeof(arr) in a function is a pointer's size, with a run as evidence.
5the bytes after two strncpy calls, with a confidence; each kernel's slowdown when n doubles.a bounded string copy and the PA1 functions by hand, edge-case tests first.the PA1 edge cases (negative, zero, NaN, non-convergence, float equality, overflow) in a table and in each function's comment, plus the question for the tutor.a tutor review against your CWE checklist; an agent's PA1 version as comparison material, never submitted.ASan, UBSan, gdb x/8cb, edge-case tests with timeout, an -O2 run, and the timing plot against your counts, in the PA1 Audit Report.your version against the agent's, and the plot's departures from n, n² and n³.
6draw the stack and heap after each line of Listing 6.13 and predict the leak report, with your confidence.by hand, a function that returns a new buffer of readings, its ownership comment written first.a question for the tutor about one report line, with your hypothesis.the tutor explains that line by asking questions, without code.ASan and LSan, Valgrind on the -O0 build, and the fail-the-k-th sweep.for every pointer, say who owns it after each line and where it is freed on each path.
7On paper: offsets and sizeof of struct reading, reordered and not; which objects rebuild after each header changes.By hand: the three headers, with guards and ownership comments.The makefile requirements: one rule per object, every header dependency, the book's flags, clean and test, and the rebuild table it must pass; plus the question for the tutor about one linker error.The tutor explains one linker error after you state a hypothesis.make -n after every touch, against gcc -MM; offsetof and ptype /o against your layout; ASan and Valgrind.The ownership rules line by line, why each item sits in the header or the source, and who frees every string.
8copy counts, growth counts and final capacity for 1,000 appends under +1 and doubling, and list drawings after three operations, each with a confidence.rvec_push with doubling and rlist_insert_after by hand, with ownership comments in the header.PA2's tests, including head-removal edge cases and the 1,000,000-append scale test with its capacity-change limit, plus the questions for the tutor.a tutor quiz on cost and drill-maker sequences to diagram; no submitted code.tests, AddressSanitizer and Valgrind, the copy counter, and a timing table and log-log sketch checked against your derivation.the growth policy, the line where the old buffer dies, the line where the head changes.
9the eight results of Listing 9.15 and the first 29 bytes of one.bin, on paper, with confidence.stn_pack_flags (Listing 9.4), then the lab reader and its handlers, by hand.the opaque sensor_db.h with its ownership comments, the stn_log status enum, and the question you put to the tutor about the dump.the tutor explains one dump or errno message you have already annotated, and writes no code you submit.truncated-file tests, the dump checked with od -j -N, ASan and UBSan on every build, Valgrind on your reader, and Listing 9.14's compile error.why the struct is hidden, why the reader checks the count, what the file looks like when the power fails.
10the bound and the slope for each sort on random, sorted, reverse and equal input, written before any timing; the comparison counts for Listings 10.1 and 10.3.insertion sort for struct reading by hand, with its own tests and timings.stn_sort.h with stability, ownership of the temporary, error returns and a complexity budget over named inputs; test_sort.c with edge, stability and hostile-input tests, compiled and failing against stubs.the Pair implements stn_merge_sort_by_time and stn_quick_sort_by_time from the spec; the Adversary proposes inputs; prompts and transcripts saved.line reading against the spec, sanitizer and Valgrind runs, your own recurrence for each function, the harness on four input kinds, and the slope compared with your derivation.why this bound, which input breaks a pivot rule, where the temporary is freed.
11What the one-line queue prints and what ASan reports; which decisions the prompt left open; how many tests the Pair's draft fails.By hand, a ring-buffer trace through wrap and growth (Table 11.2) and a small stack with its contract (Listing 11.2).rqueue.h with all seven parts, including numbered ownership rules, and test_rqueue.c, before any implementation.The Pair implements rqueue.c without changing the spec; the Adversary adds tests against the spec.Tests under ASan and UBSan, then -DNDEBUG, then Valgrind; each failure traced to a rule; bounds against the budget; keep or rewrite.The empty-queue rule, where each byte is freed, why push is amortized O(1), why the ownership section is yours.
12Before seeing the port, list which habits survive, whether output matches and whether the sanitizer reports; predict naive and memoized call counts.By hand: a stn::mean taking const std::vector<stn::Reading>&, and seam_from from the recurrence.The port spec (rules, golden output, your ownership section) and the PA4 spec (signatures, recurrence, tests, O(w × h) budget, preconditions).The Pair ports and writes min_seam_memo; save prompts and transcripts.Build with the book's line, diff, scan, read against Table 12.1, test, then count and time at increasing h against your derivation.Why the port is no longer C, where each container's memory is freed, and why the seam bound is w × h, not 3ʰ.
13Write the Image invariant, the members that could break it, and how many Adversary attacks will succeed, with a confidence.By hand: both constructors and remove_vertical_seam, with a paper trace like Table 13.2.Listing 13.13 with its invariant comment, tests with a const probe and refusal tests; public declarations do not change.The Pair implements the rest; the Adversary, with the header only, attacks the public interface.Header diff; tests under ASan and UBSan; one test per successful attack; heap totals for + against +=; the Audit Report.Five minutes: state the invariant, show where each shape-changing member restores it, explain the overflow attack and its fix.
14Without the agent, draw the timeline and memory after Buffer b = a;, predict the ASan error kind, and write cost formulas for copy and move.By hand, the copy constructor and copy-and-swap assignment.The declaration, the ownership rules (never delegated), tests from the rules, and a budget: copy proportional to n, move constant.The Pair writes the remaining members or a rule-of-zero rewrite; save the transcript.The five-member checklist, then ASan, Valgrind, the growth count and the timing; record each defect with its instrument.Where the array is freed, what a move leaves, why each pointer type.
15Before any code exists, predict each line of Listing 15.8, draw the vtables for your four sensor kinds, and count the virtual calls in a simulated day.By hand, write Sensor and one derived class, and check them against your drawing.Write the class list with is-a and has-a labels and reasons, the ownership section, the tests (including station destruction under ASan) and the checklist in Table 15.1.The Pair implements the other classes and reviews its code against your checklist; a separate Adversary session writes hostile client code.Build with -Wnon-virtual-dtor added; run ASan, UBSan and Valgrind; apply the checklist yourself; run the Adversary's cases; measure dispatch in proportion; decide keep or rewrite.In five minutes: why each inheritance is there, what happens to memory when the station is destroyed, and what dispatch costs in a simulated day.
16Which readings Listing 16.10 keeps and which build reports it; traversal times and bytes per reading for the three sequence containers at 10⁶, each with a confidence percentage.By hand: one sensor's running mean, minimum and maximum, and the max_of template.stats.hpp (Listing 16.12): interface, each container with its reason, ownership, cost budget and the edge cases tests must cover.Writer and Tester in separate sessions from the header, then the Reviewer on header and diff; transcripts saved, rounds counted.Tests built three ways; each Reviewer finding confirmed or refuted with a tool; each disagreement settled by a timing run; defects, finder and keep-or-rewrite recorded."Why this container?" and "which iterator is still valid?" for your own code, with Table 16.2 and your timings.
17Draw the trees for the six-key orders of Section 17.2, predict heights for the six adversarial orders at n = 1,023, and predict the sorted-versus-random timing ratio at 10⁵, each with a confidence level.Insert, search and in-order traversal by hand, recursively, with your own six-key test and drawings.sensor_index.hpp, the ownership rules (one owner per node; freeing never recurses), the complexity budget in terms of h, and the tests you require: random against std::set, all three delete cases, and a sorted tree deeper than Table 17.2.Writer implements erase, height, in-order and move from the header; Reviewer reads the diff for unlink paths and recursion; Tester generates adversarial orders without seeing the code.ASan and UBSan on all tests, Valgrind on a small run, Tester's heights against your predictions, the timing table against your derivation of O(log n) and O(n), and a keep-or-rewrite line for each function.Five minutes: the height after a given order, the input that breaks a plain BST, and the line where each erased node is freed.
18The bucket histogram for your hash on your keys, the resizes and moves for 10⁶ inserts, each structure's log-log slope.find, insert_or_assign and rehash by hand, and the PA6 linear scan.The PA6 header and tests, find's pointer lifetime, the exception guarantees, the complexity budget; freeze the harness.The class experiment: same spec, six calls, four configurations, relaying only.Hidden tests, sanitizers, Valgrind, histogram, three timing runs and slopes against your derivations; every review finding classified with evidence.The load factor, the input that breaks the hash, what a resize does to memory, what the plot shows.
19where two Writers will disagree on the fault rule, your corrected estimate, and the first defect the instruments will find.the plan, the alerts header with its ownership and cost comments, and the memory trace of the opening case's merge, by hand.alerts.hpp, the definition of done with its make done target, and the Tester's brief, with every Section 19.2 ambiguity decided.the Tester, then Writers on separate branches, then a Reviewer per diff, each a separate session with only its role's inputs.read each diff and its callers, classify each review, run make done after every merge, add a test, and compare actual hours with the estimate.why you accepted each merge, where every allocation is freed, and why the quadratic check is right at the stated bound.
20the counter's possible final values at 1,000 and 100,000 increments per thread, the interleavings behind them, and how many of 100 runs will be wrong.by hand, the unsafe, mutex and atomic counters, and the fix to the agent's size() and empty().the locking plan: what is shared, who touches it, which lock guards it and for how long.the Writer builds the thread-safe buffer from the plan, the Tester writes stress and late-consumer tests, the Reviewer tables every shared access.TSan under stress, repeated runs under timeout, the Reviewer's table against the plan, and timing with and without the lock.every lock's scope, every shared variable, and why a passing run is not evidence of no race.