Appendix C. Tutor Prompt and Prompt Patterns
This appendix collects the prompts the book uses, role by role, in condensed form, with the section where each is taught. The full versions, with what to hand over and how to check the answer, are in each chapter's Section N.4. Every prompt follows the same three rules.
- Your work goes first. Your prediction, your hypothesis or your spec is in the prompt before the agent says anything.
- The role and its limits are stated. What the agent may do and what it must not do are in the prompt, in the words of Table 2.4.
- The answer is checkable. Ask for numbered claims, line numbers, failing inputs or test cases, never for a verdict such as "is this right?"
C.1 The tutor prompt
Paste this at the start of every tutoring session, exactly. Save it as tutor-prompt.txt (Setting Up Your Workbench).
Listing C.1. The book's tutor prompt (canonical wording).
You are my tutor for a first course in C. Never write
more than three lines of code for me. When I ask for a
solution, ask me a question that leads me toward it.
When I show you an error, explain what the compiler or
tool is telling me, then ask what I think the fix is.
Before you explain anything about memory, ask me for my
own prediction first. Quiz me when I seem unsure.
If the tutor starts handing you code, paste the prompt again or start a new session (Section 1.4.1).
C.2 Tutor patterns
The basic move is the question for the tutor: what you ran, what you saw, what you predicted, your hypothesis and the help you want (Sections 1.4.2 and 2.2.2).
Listing C.2. The question-for-the-tutor pattern.
I built with <build line> (<file>).
First error or report: <exact first lines>
The line it points to: <one line of code>
I predicted: <value or behavior>, <__>% sure.
My hypothesis: <one sentence>.
Am I on the right track? A hint or a question, not a fix.
Paste only the first error; later ones are often its side effects. State your hypothesis even if you think it is wrong. For a sanitizer report, Chapter 6 makes the hypothesis specific enough to be wrong in a checkable way.
Listing C.3. Reading a report with the tutor (Section 6.4).
Here is a report from my program. My hypothesis, before
you answer: the bad access is <line>, the block was
allocated at <line> and freed at <line>, and the bug is
<one sentence>. I am <__>% sure. Tell me which part of my
reading is wrong, if any, by asking me a question about
that line. Do not rewrite my code.
For a pointer snippet, ask for claims you can turn into gdb commands.
Listing C.4. Numbered claims about memory (Section 4.4).
Here is a C snippet and my prediction. Explain each
line's effect on memory as numbered claims: what
changes, its new value, and where each pointer points
(e.g. "p points at a[2]"). Do not rewrite the code.
Then ask me which claim I want to check first in gdb.
Table C.1. Tutor patterns by chapter.
| Ch | You bring | You ask for | Section |
|---|---|---|---|
| 1 | Build command, first error, the line, your guess | A hint, not the fix | 1.4.2 |
| 2 | What you saw, predicted and suspect | A question about your hypothesis | 2.2.2 |
| 3 | A miss: your formula, the counter's value | A question that leads to the formula | 3.4 |
| 4 | A snippet and your drawing | Numbered memory claims to check in gdb | 4.4 |
| 5 | Your string code, checklist and findings | Pass or fail per checklist item, with the line | 5.4 |
| 6 | A report and a specific hypothesis | Which part of your reading is wrong | 6.4 |
| 7 | Linker error, link command, nm output |
Which line supports or contradicts you | 7.4 |
| 8 | Your number and reasoning on a growth policy | One cost question at a time, no answer | 8.4 |
| 9 | The format, a hex dump, your annotation | Questions on how you got each field | 9.4 |
Whatever the tutor says is testimony. Confirm it with the instrument the trust ledger names: a rebuild, gdb, nm, od, a counter or a sanitizer run.
C.3 Drill maker
Ask for questions without answers, fix the starting state so you and the agent draw the same thing, and ask for the key in a separate message after you have answered on paper (Section 2.3.2).
Listing C.5. The drill-maker pattern (after Sections 3.4 and 8.4).
Act as a drill maker for a first course in C. Give me
<n> <kind of item> starting from <fixed state>. Vary
<what>. Do not show the answers. When I post mine, tell
me which are wrong and, for each, give an input where
my answer fails or ask me a question about it.
Table C.2. Drills by chapter.
| Ch | Items to ask for | How you check the key | Section |
|---|---|---|---|
| 3 | Five loops (nested, steps other than 1, early break): count the marked line as a formula in n | A counter in the loop | 3.4 |
| 4 | Pointer expressions varying the four forms, the type and the start | Compile and run each | 4.4 |
| 5 | Ten byte-trace drills, three exactly on the boundary | x/8cb in gdb |
5.4 |
| 6 | Five 10-line programs, each with at most one leak, double free or use-after-free | Run each under ASan | 6.4 |
| 7 | Five structs with fixed-width types and double: size and every offset |
A program printing sizeof and offsetof |
7.4 |
| 8 | Insert and delete sequences on a fixed list; growth sequences under a stated policy | Write each as a program and print it | 8.4 |
| 9 | Eight expressions on a uint8_t flag byte, two with promotion, one undefined shift |
A tiny program under UBSan | 9.4 |
A drill key is testimony too. When the program and the key disagree, the program wins, and the disagreement goes in your work log.
C.4 Confused peer
The agent plays a student who holds one stated misconception and defends it until you produce evidence. It must not drop the act and correct itself; if it gives in at once, restart it.
Listing C.6. The confused-peer pattern (after Section 4.4).
Play a first-year C student who firmly believes that
<misconception>. Defend it as a student would. Change
your mind only for evidence you cannot explain away,
and say exactly what convinced you.
Make the peer commit to a prediction, then show the run that breaks it, as Priyanka does in Section 4.4.
Table C.3. Misconceptions to assign, by chapter.
| Ch | The peer believes | Your evidence | Section |
|---|---|---|---|
| 2 | A program with no ASan report has no bugs | The all-missing test that prints -nan |
2.3.2 |
| 3 | A local keeps its value after its function returns | Listing 3.4 and the frame-pop step | 3.4 |
| 4 | sizeof(arr) in a function gives the array's length |
Runs printing 48 and 8; the gcc warning | 4.4 |
| 5 | strlen counts the terminator, so char id[4] holds "1001" |
Figure 5.1, Listing 5.2, your ASan report | 5.4 |
| 6 | free(p) sets p to NULL, so a second free is safe |
The gdb session of Section 6.1.4; the report from Listing 6.7 | 6.4 |
| 9 | fread always returns what you asked for |
Listing 9.2's output, a truncated file, an ASan report | 9.4 |
C.5 Pair
From Chapter 10 the agent may write code, under one rule: you write the spec first, completely, and the agent may not change it. The spec has four parts (Section 10.4): the header, the tests, the complexity budget and the ownership rule. The prompt hands over the first three as fixed and the fourth as yours.
Listing C.7. The spec-to-pair pattern (after Sections 10.4.1 and 11.4.1).
You are my pair programmer. Implement <file.c> for the
header and tests below. Do not change the header or the
tests. Follow the numbered OWNERSHIP and ERRORS rules
exactly, citing rule numbers in comments. Meet the
COMPLEXITY BUDGET. Use only <library>. Build with
<build line>. List every assumption the spec does not
state. If any line of the spec seems wrong or ambiguous,
reply with one question instead of code.
Chapter 10's version adds "Return the code and nothing else: no claims about complexity", because you derive the bound yourself. Chapter 11's asks the Pair to put its representation invariant at the top and state each function's bound, which you then check rather than copy. Both endings matter: a question from the Pair is an ambiguity in your spec, and a list of assumptions is a list to verify.
Table C.4. What the Pair gets in each chapter.
| Ch | The Pair writes | You hand over, fixed | Section |
|---|---|---|---|
| 10 | stn_sort.c (merge sort and quicksort) |
stn_sort.h with ownership, errors and budget; test_sort.c |
10.4.1 |
| 11 | rqueue.c or your chosen container |
The seven-part header, the tests, check.h, the build line |
11.4.1 |
| 12 | A C++20 port of a C tool; PA4's min_seam_memo |
The habit rules, golden.txt, your ownership section; your recurrence and tests |
12.4 |
| 13 | stn::Image member functions |
The declaration with the invariant comment; your tests | 13.4 |
| 14 | The five special members of stn::Buffer; a rule-of-zero rewrite in the lab |
The declaration and the ownership rules | 14.4.2 |
| 15 | Sensor kinds, Calibration, Channel, Station |
Class list with is-a or has-a labels, ownership, tests, Table 15.1 | 15.4 |
Two Pair prompts end with a request that turns a claim into a checklist. Chapter 12's port prompt ends "list every place you could not follow a rule"; Chapter 13's asks, for each non-const member, "name the line where the invariant may be false and why no caller can observe it." Check both lists anyway.
C.6 Adversary
The Adversary attacks: with hostile inputs, with tests your suite lacks, or with realistic planted bugs. Give it the interface and the rules, not the implementation (unless the attack is on the finished code), and ask for inputs or tests, not fixes. Reject textbook attacks that any implementation passes.
Listing C.8. The input-attack pattern (Section 10.4.1).
Act as an adversary for the functions declared in
<header> (attached). Do not write or fix the code.
Propose <n> inputs, each with: how to generate it for
any n, which implementation choice it is designed to
break, and what failure I should see. Include at least
one input that is not sorted, reversed or all equal.
Chapter 14 promised its Adversary prompt here. It attacks a finished resource-owning class with realistic misuse and must predict each failure, so you can score it against ASan.
Listing C.9. The Adversary for a resource-owning class (Section 14.4.2).
You are an adversary for the class in buffer.hpp and
its ownership rules (attached). Do not fix anything.
Write <n> short test programs that misuse it the way
real code does: copies through containers, aliased
self-assignment, use after move, an observer that
outlives its owner. For each, predict the failure:
the ASan error kind and line, or "silent", and why.
Table C.5. The Adversary by chapter.
| Ch | Target | Ask for | Section |
|---|---|---|---|
| 10 | Sort functions, from the header and budget | Eight inputs, each naming the choice it attacks (pivot, partition, merge tie, buffer, depth) | 10.4.1 |
| 11 | Your spec and tests | Up to three tests your suite would miss, preferably against a simple model | 11.4.1 |
| 12 | Your finished port; the seam code | Three planted C habits and one output change, unmarked; hostile images (width 1, height 0, all equal) | 12.4 |
| 13 | stn::Image, public interface only |
Test programs that break the invariant or read outside the pixels, without casts or #define |
13.4 |
| 14 | The finished stn::Buffer or ReadingLog rewrite |
Misuse with predicted failures (Listing C.9) | 14.4.2 |
| 15 | Your design and headers, in a session apart from the Pair | Cases that slice, leak, misdispatch through the base or duplicate a sensor ID | 15.4 |
Every Adversary test joins your suite only after you agree the spec requires what it checks (Section 11.4.1).
C.7 Writer, Reviewer and Tester
In the Team phase each role is a separate session that sees only what it needs. The Writer sees the header and build line, the Tester sees the header alone, and the Reviewer sees the header and the diff but never the Writer's explanation (Sections 16.4 and 19.3.1). You alone see all three, and you merge.
Listing C.10. The Writer (after Sections 16.4 and 19.4.1).
You are the Writer. Implement exactly the functions
declared in <header> in <file>. Do not change the
header or any file outside <directory>. Use the
containers it names; if another is better, say why in
a note at the end, but do not use it. If the spec is
ambiguous, stop and ask. Report every place you
allocate or store a pointer, reference or view. Build
with <build line> and paste the output. Do not write
tests.
Listing C.11. The Reviewer, memory first (Section 19.4.1).
You are the Reviewer. Inputs: the diff and <headers>.
Do not rewrite the code. Before any style comment,
answer for every changed function:
(1) Who owns each pointer, reference or view it creates
or returns, and where is it freed? Quote the line.
(2) Did its contract change? List the callers I must
read.
(3) Which input reaches the boundary of each condition?
Then list style comments separately, marked STYLE.
Name the categories where you found nothing.
Listing C.12. The Tester (after Sections 16.4 and 20.4).
You are the Tester. Below is a header. You will not see
the implementation. Write assert-based tests: empty
input; one item; each boundary exactly at, one step
inside and one step outside; hostile and interleaved
cases; a large case with checked counts. One comment
line above each test saying what it checks. Exit
non-zero on failure. Do not implement or fix anything.
Table C.6. Team prompts by chapter.
| Ch | Writer | Reviewer | Tester | Section |
|---|---|---|---|---|
| 16 | stats.cpp from stats.hpp |
Invalidation, string_view lifetimes, containers against the budget, ranked |
Empty, one, invalid runs, shuffled sensors, 100,000 readings | 16.4 |
| 17 | erase, height, ids_in_order and the moves of stn::SensorIndex; no recursion, no delete |
Every unlink and what frees it; every place stack depth grows with the tree | Adversarial insert orders from the header alone; heights printed, never predicted for you | 17.4 |
| 18 | stn::ReadingTable, edits only src/ |
Configurations B, C and D (Table 18.3); D uses the six-item hash checklist | Hidden tests are yours, frozen outside the agent's tree | 18.4.1 |
| 19 | One task per branch, make done |
Ownership, contract change and boundaries before style | Boundaries, other flag bits set, interleaved sensors | 19.4.1 |
| 20 | stn::RingBuffer from the locking plan |
A table of shared variables, lines and locks held; flags waits without predicates and I/O under a lock | Two producers, one consumer, 100,000 each, a late consumer | 20.4 |
Chapter 18's configurations keep the prompts fixed so that only the structure varies. Configuration B asks the same session to "review the code you just wrote against the spec ... then revise it"; C asks a new session to review "a colleague's code" with line numbers and reasons; D gives the new session a numbered checklist with pass or fail and evidence for each item (Section 18.4.1).
C.8 What never goes into a prompt
Five things are never delegated, in any phase (Chapter 2): the first prediction, the first debugging hypothesis, the ownership and lifetime section of a spec, the final judgment that code is correct, and the memory checkpoint. Chapter 19 adds, for teams: the plan and its estimate correction, conflict resolution and the explain-back. Chapter 20 adds the locking plan. Write each one yourself first. An agent may then critique what you wrote; none of them may start as an agent's draft.