Appendix A. Audit Report Template

The Audit Report records step 5 of the working loop (Chapter 2): what you specified, what the agent did, and what the instruments said. Chapter 2 introduces it, Chapter 5 shows the first complete one (Section 5.5.1), and every programming assignment from PA1 onward ends in one. It is one to two pages in seven numbered parts, always in this order, so that a reader (the instructor, the teaching assistant at your oral defense, or you in three weeks) can find any piece of evidence without searching.

Write parts 1 and the predictions behind part 5 before you delegate anything. A specification written after reading the agent's code describes the code, not what you wanted, and an Audit Report built on it audits nothing.

A.1 The seven parts

Table A.1. The seven parts, with one line of guidance each.

Part Title What goes in it
1 Specification Interface, tests, ownership rules and complexity budget, written before delegating (Tutor phase: your question and your own design)
2 Agent log Roles used, key prompts, number of rounds; transcripts attached
3 Correctness evidence Test results, including the tests you added after reading the agent's work
4 Memory-safety evidence Output from -fsanitize=address,undefined and Valgrind (TSan in Chapter 20), clean or not
5 Complexity analysis Your derivation (input sizes, dominant operation, bounds and their conditions) against a timing plot at increasing n
6 Defects found What went wrong, who made it, which instrument found it, the fix
7 Decision Keep, rewrite or partly rewrite, and why

A few rules apply to every part.

  • Evidence, not adjectives. "Clean under ASan" is a claim; the last lines of the run are evidence. Paste trimmed output with the command line.
  • Name the instrument. Each defect in part 6 names what found it: a test, ASan, UBSan, LeakSanitizer, Valgrind, TSan, gdb, a debug-container build, a timing run, a hand trace or your prediction.
  • Testimony is labeled. If an agent's claim appears anywhere, say it is the agent's and say how you checked it (Chapter 2's trust ledger).
  • Before Chapter 10, part 5 holds an informal count (how many times the loop body runs, how many readings are copied) rather than a formal bound.
  • Sometimes the simple version is right. Part 7 may keep an agent's code, keep your own, or keep a quadratic solution whose bound you can defend (Section 19.1.8).

A.2 The fill-in template

Copy this into your report file and replace every line in angle brackets. Keep the numbering.

Listing A.1. The Audit Report skeleton (audit.md).

AUDIT REPORT: <assignment or lab>   <your name>   <date>

1. Specification (written <date>, before delegating;
   commit <hash>)
   Interface:   <header file, or the question you asked>
   Ownership:   <numbered rules: who allocates, who frees,
                 how long each borrowed pointer lives>
   Errors:      <status codes and what changes on failure>
   Budget:      <time and space bounds, on which inputs>
   Tests:       <count; list edge and hostile cases>

2. Agent log
   Roles:       <Tutor / Pair / Adversary / Writer ...>
   Sessions:    <n>   Prompts: <n>   Rounds: <n>
   Key prompt:  <one line, or "see transcript 2a">
   Transcripts: <file names>

3. Correctness evidence
   <tests run, passed, failed; command and last lines>
   Added after reading the code: <tests and why>

4. Memory-safety evidence
   ASan + UBSan: <clean, or first lines of each report>
   Valgrind:     <HEAP SUMMARY and ERROR SUMMARY lines>
   Other:        <TSan, -D_GLIBCXX_DEBUG, failure sweep>

5. Complexity analysis
   Variables:   <n = ..., m = ...>
   Dominant op: <comparison, copy, multiply ...>
   Derivation:  <count or recurrence, your own work>
   Bound:       <time, space, and the conditions>
   Measured:    <sizes, times, log-log slope; plot>
   Agreement:   <where derivation and plot differ, why>

6. Defects found
   D1 <who> <what> found by <instrument>; fix: <...>
   D2 ...

7. Decision
   <keep / rewrite / partly rewrite> because <evidence>

A.2.1 Variations by phase and chapter

Table A.2. Where the parts change shape.

Where Part What changes
Tutor phase (Chapters 1 to 9) 1, 2 Part 1 holds your question and your design; part 2 logs tutor, drill-maker and confused-peer sessions; no agent code is submitted
PA1 (Chapter 5) 2, 6 An agent version written for comparison only may be audited in part 6; it is never submitted
Pair phase (Chapters 10 to 15) 1, 6 Part 1 is the full spec of Chapter 11; part 6 ties each defect to a numbered rule
PA5 (Chapter 15) 5 The day's dispatch cost, in proportion to the cost of writing the day's log
PA6 (Chapter 18) 5 Derivations against slopes, the timing table and plot, and the bucket histogram
Capstone (Chapter 19) 6 Every defect, what found it, and any the Reviewer missed
Concurrency lab (Chapter 20) 1, 4, 5 The locking plan is the spec; TSan evidence in part 4; worst lock wait in part 5

A.3 A filled example: PA2

A composite report, as Maya might write it; not a real student or course. Numbers are illustrative except where they repeat a run printed in Chapter 8.

1. Specification. PA2 interface exactly as Chapter 6 fixed it, plus rvec_capacity (Chapter 8). Ownership, in my header comments: (1) the caller owns what rvec_new and rlist_new return and passes it to the matching _free once; _free(NULL) is safe; (2) readings are copied in; (3) the container owns its buffer or nodes; (4) rvec_get returns a borrowed pointer valid until the next push or free, because growth may move the block. Errors: every -1 changes nothing. Budget: n pushes copy fewer than 2n readings (doubling from capacity 8); rlist_remove_at is linear in the index. Tests written first: 23, including remove at index 0, at the last index, on a one-node list and past the end; rvec_get past the end; rvec_free(NULL); a failure sweep over every allocation.

2. Agent log. Tutor phase: no agent code. Tutor, two sessions, 7 prompts: a cost quiz on growth policies (Section 8.4) and one question about a LeakSanitizer report, hypothesis stated first. Drill maker, one session, five list-operation sequences; I drew all five before opening the key. Transcripts t1.txt to t3.txt attached.

3. Correctness evidence. 23 of 23 tests pass under the book's build line. Added after the first full run: removing the head of a two-node list followed by rlist_get(l, 0), because my drawing of that case had an arrow I could not justify. The scale test (Listing 8.10's pattern, my own limits) printed 1000000 appends, 18 capacity changes, inside my prediction of 17 to 18.

4. Memory-safety evidence. ASan and UBSan clean on all tests. Valgrind (-O0, no sanitizers): All heap blocks were freed -- no leaks are possible, ERROR SUMMARY: 0 errors. The fail-the-k-th-allocation sweep (Section 6.1.9) ran for every k up to the number of allocations in the test; LeakSanitizer is silent on every k after the fix in D1.

5. Complexity analysis. Variable: n, the number of pushes. Dominant operation: copying one reading during growth. With doubling from 8, the copies are 8 + 16 + ... + 524,288 = 1,048,568 for n = 1,000,000, which is below 2n. Each push is O(1) amortized; the occasional push that grows is O(n). Measured at -O2 from 1,000 to 1,024,000 pushes: log-log slope 1.0 for rvec push. rlist append at the end, which walks the list, gave slope 2.0 up to 64,000, as an O(n) walk per append predicts. Plot attached.

6. Defects found.

  • D1 (mine): rvec_push assigned realloc straight back to v->data, so a failed growth lost the only pointer to the old block. Found by the failure sweep (LeakSanitizer reported one direct leak on the failing k); fix: assign to a temporary and keep the old block on failure (Section 6.3.3).
  • D2 (mine): rlist_remove_at past the end decremented the size before checking the index. Found by my past-the-end test; fix: check first, change nothing on -1.
  • D3 (tutor's claim): "1,000 doubling appends copy about 1,024 elements." Checked by running Listing 8.8, which starts at capacity 0 and printed 1,023 copies, and by counting in my own rvec, which starts at 8: 1,016. Right about the shape, wrong about the number; logged on the ledger as testimony.

7. Decision. Keep both modules. Keep doubling: the spare capacity is at most half the block, which at 32 bytes a reading is about 16 MB in the worst case at 10⁶ readings, acceptable on the station laptop. Prefer rvec for the station's time-ordered appends and scans; rlist stays for the assignment's interface comparison.