Code Comprehension Part 2: Tests & Cross-File Flow
Part 2 of the code comprehension tutorial. Return a few days after Part 1, then practice testing hypotheses with Node.js behavior tests and mapping interactions across React and backend files in a roughly one-hour session. Later quizzes interleave material from Part 1 and earlier Part 2 steps — don't be surprised if a Part 2 question asks about Part 1 vocabulary.
Retrieval Warm-Up
Welcome back to Part 2
Before opening any code, let’s see what stuck from Part 1. The next quiz is a quick retrieval check — try to answer from memory before peeking at your Part 1 notes or scrolling back.
Why this comes first: research on spaced retrieval is unambiguous (Karpicke & Roediger, Science 2008). The act of retrieving is what builds durable memory. Re-reading the routine here would feel like consolidation but actually do nothing. So the routine is intentionally NOT re-displayed before the quiz — and the quiz is the first thing you do this session.
If you can’t recall something, that’s fine. Answer your best guess. The retrieval attempt is what matters. After the quiz, the rest of Part 2 will rebuild the vocabulary on demand.
Use recall-notes.md to write down what you remember on your own first, then take the quiz.
# Part 1 Recall — open writing
Take 2–3 minutes. Without looking at your Part 1 notes or scrolling
back, write down whatever you remember about how to read unfamiliar
code quickly. Routine, vocabulary, traps you noticed, examples that
stuck. Sentences, bullet points, sketches — whatever comes out.
Whatever you can't recall is exactly what the next quiz will probe.
The retrieval *attempt* is what builds memory, not the structured
checklist. Don't pre-organize.
Step 1 — Retrieval Check
Min. score: 80%1. What is the second step of the Part 1 reading routine — the move that follows Orient?
The full routine: Orient → Predict → Beacon-hunt → Descend selectively → Verify → Summarize. Predict turns orientation into a hypothesis you can test, before any code is read in detail.
2. Name one switch trigger — a signal that you should stop scanning and start tracing line by line.
The three reliable switch triggers from Step 1 of Part 1: vague beacon, risky branch, or a contradiction between code and a test. Strong readers keep scanning until one of those fires.
3. Which are beacon types you classified in Step 3 of Part 1? (select all that apply)
Four beacon types: lexical, structural, framework, specification. Aesthetic cleanliness is a comfort signal, not a behavior signal.
4. What does the EiPE explanation frame stand for?
Explain in Plain English (EiPE): Purpose (what the code is for), Mechanism (the plan it uses), Evidence (the names/tests/branches that prove it), Limit (what you have not verified). The Limit line is what separates honest readers from overconfident ones.
5. A variable named best_so_far updates only when a new candidate scores higher. Which role from Step 5 of Part 1 does it play?
Variable roles compress several lines into one mental chunk. best_so_far paired with a > best_score guard is the textbook best-so-far / max-tracking plan. Recognizing the role lets you skip line-by-line tracing of the loop body.
6. Step 7 of Part 1 introduced false-beacon discipline. Which statement best captures that idea?
False-beacon discipline is the Faculty Mixer / pinned lesson: the field really exists, but it is not what decides visibility for this question. The test is always where the cue sits in the runtime flow.
Tests as Specification Beacons
Why this matters
If you just finished the basics tutorial today, stop here and come back in two or three days. That pause forces retrieval, which is exactly what makes the skill stick. When you return, this step starts with one of the strongest professional beacons: tests that describe the behavior before you read the implementation.
🎯 You will learn to
- Use Node.js tests to form a behavior hypothesis
- Verify one expectation by reading the smallest relevant helper
- Decide when a test is a trustworthy beacon and when it needs implementation evidence
Retrieval Warm-Up
Before opening the code, recall the Part 1 routine without looking:
Orient → Predict → Beacon-hunt → Descend selectively → Verify → Summarize
Then name one switch trigger. For example: if a behavior depends on a risky branch, stop scanning and trace one input through that branch.
Tests First
Students often read tests only after code fails. For comprehension, read them before production code:
- Test names tell you the intended behavior.
- Setup data tells you the important objects.
- Assertions tell you the invariant or postcondition.
- Failing cases tell you where the implementation is risky.
Contract-to-Mechanism Map
After reading tests, write a tiny contract map before implementation:
| Contract clue | Mechanism to verify |
|---|---|
| “returns only sessions that fit” | A filter or guard using minutes |
| “prefers a matching topic” | A ranking or scoring rule using topic |
| “low energy gives solo sessions a boost” | A branch involving energy and mode |
This keeps your attention on the behavior the tests actually promise. You can always trace more later, but first you should know what you are trying to prove.
Contrast Set
The tests have similar surface shapes, but they point to different implementation responsibilities:
| Test clue | Similar surface shape | Different mechanism to inspect |
|---|---|---|
| “returns the only session that fits” | Calls pickSessionPlan() and checks returned titles |
Minutes filter |
| “places a matching topic first” | Calls pickSessionPlan() and checks returned titles |
Scoring plus sort order |
| “solo sessions a low-energy bonus” | Uses the same request fields | scoreSession() branch |
Same test shape, different implementation responsibility. Do not read every public-function test as pointing to the same line of code.
In this step, read sessionPlanner.test.js before sessionPlanner.js. Your first hypothesis should be about behavior, not implementation:
“This planner probably returns short study sessions that fit the time box, prefers matching topics, and adjusts for energy level.”
Then inspect only the helper that can confirm each part.
One syntax note: .sort((left, right) => scoreSession(right, request) - scoreSession(left, request))
puts higher-scoring sessions first. You do not need to master every
sorting detail here; just connect that expression to the ranking behavior
named by the tests.
const SESSIONS = [
{ id: 1, title: "Trace one Python helper", topic: "python", minutes: 10, mode: "solo" },
{ id: 2, title: "Pair-read a React component", topic: "react", minutes: 18, mode: "pair" },
{ id: 3, title: "Map an Express route", topic: "node", minutes: 16, mode: "solo" },
{ id: 4, title: "Sketch a full review plan", topic: "review", minutes: 30, mode: "pair" },
];
function scoreSession(session, request) {
let score = 0;
if (session.topic === request.topic) {
score += 5;
}
if (session.minutes <= request.minutes) {
score += 2;
}
if (request.energy === "low" && session.mode === "solo") {
score += 2;
}
if (session.minutes > request.minutes) {
score -= 10;
}
return score;
}
function pickSessionPlan(request) {
return SESSIONS
.filter(session => session.minutes <= request.minutes)
.sort((left, right) => scoreSession(right, request) - scoreSession(left, request))
.slice(0, 2)
.map(session => session.title);
}
module.exports = { pickSessionPlan, scoreSession };
const test = require("node:test");
const assert = require("node:assert/strict");
const { pickSessionPlan, scoreSession } = require("./sessionPlanner");
test("returns the only session that fits a 12-minute request", () => {
const plan = pickSessionPlan({ topic: "python", minutes: 12, energy: "high" });
assert.deepEqual(plan, ["Trace one Python helper"]);
});
test("places a matching topic first when it fits", () => {
const plan = pickSessionPlan({ topic: "node", minutes: 18, energy: "high" });
assert.equal(plan[0], "Map an Express route");
});
test("scoreSession gives solo sessions a low-energy bonus", () => {
const soloScore = scoreSession(
{ title: "Solo", topic: "python", minutes: 10, mode: "solo" },
{ topic: "react", minutes: 20, energy: "low" }
);
const pairScore = scoreSession(
{ title: "Pair", topic: "python", minutes: 10, mode: "pair" },
{ topic: "react", minutes: 20, energy: "low" }
);
assert.equal(soloScore, pairScore + 2);
});
Step 2 — Knowledge Check
Min. score: 80%
1. What behavior hypothesis should the tests give you before reading sessionPlanner.js?
The tests give a specification-layer summary: fit the time, rank matching topics, and adjust scoring for low energy.
2. Which implementation region verifies the hypothesis that unavailable long sessions are excluded?
The filtering predicate is the shortest verification path for the minutes invariant.
3. A low-energy request should favor solo sessions. What is the smallest useful trace?
Targeted tracing means choosing the one comparison that exercises the uncertain branch.
4. Which cues make the tests useful beacons rather than just grading tools? (select all that apply)
Tests help comprehension when their names, setup, and assertions reveal intent.
5. What behavior is not fully specified by these tests?
Tests are powerful specification beacons, but they are not complete specifications. Strong readers also notice what a test suite leaves open.
6. You read sessionPlanner.test.js and have a contract-shaped hypothesis. What is the next routine move before reading every line of sessionPlanner.js?
Routine recap (Part 1, Step 1): tests give you the spec layer (Orient + Predict). The next move is beacon-hunting in the implementation, then descending selectively into the helpers that match each contract clause. Never trace before the hypothesis exists.
7. Two tests both call pickSessionPlan() and assert returned titles. What contrast should guide your implementation reading?
Variation Theory: hold the test surface mostly constant, then vary the contract clue. The mechanism that matters is the feature that changes.
Node Hypothesis Sprint
Why this matters
Backend code often spreads behavior across route handlers, services, and data modules. Reading everything from top to bottom burns attention on details before you know what matters. This sprint asks you to read tests as beacons, choose a route, and trace only the path needed to answer the questions. Treat the timer as feedback about your reading path, not a grade.
🎯 You will learn to
- Apply tests-as-specification reading to a multi-file Node.js example
- Trace request data from a route handler into a service helper
- Identify when a 404 behavior is implemented in the route rather than the data layer
Reading Goal
You have 10 minutes. Read in this order:
__tests__/sessionRoutes.test.jsroutes/sessionRoutes.js- Only the service helper needed for the current question
- Write a one-line contract-to-mechanism note: expected behavior → code region that enforces it.
fakeResponse() is only a small test double for Express’s res object.
Read its status() and json() methods only enough to know what the
route sent; do not treat it as production behavior.
Use reading-notes.md to write your reading path. Core target: answer
the route and service questions. Stretch target: locate where a field
leak would begin.
Practice mode: on your first attempt, use the +5 min button if you are
still collecting evidence. On a replay, try finishing inside the original
10 minutes. Before the quiz, write one reflection line about what you
inspected first, what you skipped, and what evidence changed or confirmed
your hypothesis.
Do not edit the code. Your job is to answer with evidence.
# Node Hypothesis Sprint Notes
Contract hypothesis:
Top 3 beacons:
1.
2.
3.
What I can ignore for this question:
Smallest trace:
Final EiPE summary:
Timer reflection:
- First thing I inspected:
- Detail I deliberately skipped:
- Evidence that changed or confirmed my hypothesis:
const sessions = [
{ id: 1, title: "Python filter drill", topic: "python", minutes: 12, nextStep: "Trace one hidden item" },
{ id: 2, title: "React callback map", topic: "react", minutes: 18, nextStep: "Follow the callback prop" },
{ id: 3, title: "Node route map", topic: "node", minutes: 16, nextStep: "Read tests before routes" },
];
module.exports = { sessions };
const { sessions } = require("../data/sessions");
function findSessions(topic) {
if (!topic || topic === "all") {
return [...sessions];
}
return sessions.filter(session => session.topic === topic);
}
function findSessionById(id) {
return sessions.find(session => session.id === id);
}
function toSummary(session) {
return {
id: session.id,
title: session.title,
minutes: session.minutes,
};
}
function withNextStep(session) {
return {
...toSummary(session),
topic: session.topic,
nextStep: session.nextStep,
};
}
module.exports = { findSessions, findSessionById, toSummary, withNextStep };
const {
findSessions,
findSessionById,
toSummary,
withNextStep,
} = require("../services/sessionService");
function listSessions(req, res) {
const topic = req.query.topic || "all";
const summaries = findSessions(topic).map(toSummary);
return res.json(summaries);
}
function sessionDetails(req, res) {
const id = Number(req.params.id);
const session = findSessionById(id);
if (!session) {
return res.status(404).json({ error: "session not found" });
}
return res.json(withNextStep(session));
}
module.exports = { listSessions, sessionDetails };
const test = require("node:test");
const assert = require("node:assert/strict");
const { listSessions, sessionDetails } = require("../routes/sessionRoutes");
function fakeResponse() {
return {
statusCode: 200,
body: undefined,
status(code) {
this.statusCode = code;
return this;
},
json(payload) {
this.body = payload;
return this;
},
};
}
test("GET /sessions?topic=react returns only React summaries", () => {
const res = fakeResponse();
listSessions({ query: { topic: "react" } }, res);
assert.equal(res.statusCode, 200);
assert.deepEqual(res.body, [
{ id: 2, title: "React callback map", minutes: 18 },
]);
});
test("GET /sessions/:id includes the next recommended step", () => {
const res = fakeResponse();
sessionDetails({ params: { id: "3" } }, res);
assert.equal(res.statusCode, 200);
assert.equal(res.body.nextStep, "Read tests before routes");
});
test("GET /sessions/:id returns 404 for a missing session", () => {
const res = fakeResponse();
sessionDetails({ params: { id: "99" } }, res);
assert.equal(res.statusCode, 404);
assert.deepEqual(res.body, { error: "session not found" });
});
Step 3 — Knowledge Check
Min. score: 80%
1. For GET /sessions?topic=react, what is the request-data path?
The query value is read at the route boundary, passed to the service, and only then mapped into response summaries.
2. Where is the missing-session 404 response implemented?
The route owns HTTP response shape. The service owns data lookup.
3. Which helper should you inspect to answer why nextStep appears in the details response but not the list response?
listSessions() maps through toSummary(), while sessionDetails() returns withNextStep(session).
4. Which files are central implementation evidence for the missing-session 404 behavior? (select all that apply)
Attention control means separating specification evidence, central implementation evidence, and supporting data.
5. A bug report says the list endpoint is leaking nextStep. Where should the search start?
Concept location starts from the user-visible concept, then follows the route boundary to the helper that shapes the response.
6. In routes/sessionRoutes.js::listSessions(), what role does the local summaries value play?
Variable roles (Part 1, Step 5) carry over to JavaScript. .filter(...).map(...) chains produce a gatherer — the value that holds the shaped collection until it is returned. Recognizing the role lets you skim the .map callback once you know what’s coming out.
Cross-File Interaction Maps
Why this matters
Large code rarely keeps cause and effect in one place. A click in one React file may update state in another file and change rendering in a third. Cross-file comprehension means turning scattered code into a small interaction map.
🎯 You will learn to
- Map event flow across parent and child React components
- Identify which file owns state and which files only receive props
- Verify a cross-file hypothesis by following one callback path
The Interaction Map
Use a four-column map. This one is partly worked; fill the blanks in your own notes before checking the code.
| Trigger | File / component | Evidence | Effect |
|---|---|---|---|
| User types in search box | LessonSearch |
onChange={event => onQueryChange(...)} |
Calls parent callback |
| Parent callback runs | _____ | onQueryChange={setQuery} |
Updates query state |
| Derived list recalculates | App |
_____ | Chooses visible lessons |
| List renders | LessonList |
lessons.map(...) |
_____ |
The point is not to memorize React syntax. The point is to name the connection between separated locations.
Predict Before Reading
Before opening every file, predict which file owns:
- the search text,
- the selected lesson,
- the display of matching lessons.
Then verify by following the callback props.
:root {
--page-bg: #f6f8fb;
--panel-bg: #ffffff;
--text: #172033;
--muted: #526070;
--border: #c7d2df;
--accent: #00598c;
--accent-strong: #00466d;
--button-text: #ffffff;
--status-bg: #e5f2ff;
--focus: #ffbf47;
}
html.dark-mode {
--page-bg: #101827;
--panel-bg: #1d2736;
--text: #f4f7fb;
--muted: #c8d2de;
--border: #516174;
--accent: #7cc7ff;
--accent-strong: #a7dcff;
--button-text: #08111d;
--status-bg: #1f3850;
--focus: #ffd166;
}
body {
margin: 0;
background: var(--page-bg);
color: var(--text);
font: 16px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.lesson-shell {
max-width: 900px;
margin: 0 auto;
padding: 24px;
}
.lesson-shell h1 {
margin-block: 0 18px;
font-size: 1.8em;
}
.search-label {
display: grid;
gap: 6px;
max-width: 360px;
font-weight: 700;
}
.search-label input {
min-height: 40px;
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 10px;
background: var(--panel-bg);
color: var(--text);
font: inherit;
}
.search-label input::placeholder {
color: var(--muted);
opacity: 1;
}
.selection-status {
border: 1px solid var(--accent);
border-radius: 8px;
padding: 10px 12px;
background: var(--status-bg);
color: var(--text);
font-weight: 700;
}
.lesson-list {
display: grid;
gap: 12px;
margin-block-start: 18px;
}
.lesson-card {
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
background: var(--panel-bg);
box-shadow: 0 2px 8px rgb(23 32 51 / 0.08);
}
html.dark-mode .lesson-card {
box-shadow: 0 2px 10px rgb(0 0 0 / 0.35);
}
.lesson-card h2,
.lesson-card p {
margin: 0 0 8px;
}
.lesson-card h2 {
font-size: 1.2em;
}
.lesson-card p {
color: var(--muted);
}
.lesson-card button {
min-height: 40px;
min-width: 92px;
border: 2px solid var(--accent);
border-radius: 6px;
padding: 8px 14px;
background: var(--accent);
color: var(--button-text);
font: inherit;
cursor: pointer;
}
.lesson-card button:hover {
border-color: var(--accent-strong);
background: var(--accent-strong);
}
.lesson-shell :focus-visible {
outline: 3px solid var(--focus);
outline-offset: 3px;
}
const LESSONS = [
{ id: 1, title: "Python filters", tag: "python", minutes: 12 },
{ id: 2, title: "React callbacks", tag: "react", minutes: 18 },
{ id: 3, title: "Node route tests", tag: "node", minutes: 16 },
];
function LessonSearch({ query, onQueryChange }) {
return (
<label className="search-label">
Search lessons
<input
value={query}
onChange={event => onQueryChange(event.target.value)}
placeholder="python, react, node..."
/>
</label>
);
}
function LessonList({ lessons, selectedId, onSelectLesson }) {
return (
<section className="lesson-list" aria-label="Matching lessons">
{lessons.map(lesson => (
<article className="lesson-card" key={lesson.id}>
<h2>{lesson.title}</h2>
<p>{lesson.minutes} minutes</p>
<button type="button" onClick={() => onSelectLesson(lesson.id)}>
{selectedId === lesson.id ? "Selected" : "Select"}
</button>
</article>
))}
</section>
);
}
function App() {
const [query, setQuery] = React.useState("");
const [selectedId, setSelectedId] = React.useState(null);
const normalizedQuery = query.trim().toLowerCase();
const visibleLessons = LESSONS.filter(lesson =>
lesson.title.toLowerCase().includes(normalizedQuery) ||
lesson.tag.includes(normalizedQuery)
);
const selectedLesson = LESSONS.find(lesson => lesson.id === selectedId);
return (
<main className="lesson-shell">
<h1>Lesson Finder</h1>
<LessonSearch query={query} onQueryChange={setQuery} />
{selectedLesson && (
<p className="selection-status" role="status">
Selected: {selectedLesson.title}
</p>
)}
<LessonList
lessons={visibleLessons}
selectedId={selectedId}
onSelectLesson={setSelectedId}
/>
</main>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
Step 4 — Knowledge Check
Min. score: 80%
1. A user types node in the search input. What is the correct interaction path?
The search behavior crosses files through a callback prop and derived state in the parent.
2. Which file owns selectedId?
In React, state ownership is usually marked by useState; child components receive values and callback props.
3. Which evidence proves that LessonList is display-and-event wiring, not the owner of lesson filtering?
LessonList renders whatever list it receives; filtering happens before the prop crosses into the component.
4. Which cross-file links should appear in an accurate interaction map? (select all that apply)
Cross-file maps should include both upward callback flow and downward data flow.
5. When should you switch from beacon reading to a small bottom-up trace in this React example?
A callback crossing a file boundary is a good switch point: predict from the prop name, then trace one event path.
6. A reader claims that lesson.tag.includes(normalizedQuery) alone is the central evidence for what the search box does. What is the false-beacon-aware response?
False-beacon discipline (Part 1, Step 7): a true expression can still be partial evidence. The full predicate uses || over two matchers; reasoning from one branch without the other is a hypothesis you have not yet verified.
Backend Interaction Sprint
Why this matters
This final sprint combines the whole routine: orient from tests, predict the design, find beacons, trace one risky branch, and map files. It is also a concept-location task: you start with a domain idea such as “coupon” or “out of stock” and locate the files that realize it. The code is bigger than before, but the reading job is still bounded. Use the timer to calibrate your search path, not to rush.
🎯 You will learn to
- Map request data through route, service, data, and discount helpers
- Verify one error path without tracing the entire backend
- Evaluate when a helper name is a reliable beacon for responsibility
Reading Goal
You have 15 minutes. Read __tests__/checkoutRoute.test.js first. Then answer:
- What happens when an item is out of stock?
- Where is the coupon applied?
- Which helper computes the subtotal?
- Which files participate in a successful quote?
- Which files are central, supporting, or incidental to the concept you are investigating?
Use reading-notes.md to write a narrow interaction map. Core target:
stock, subtotal, and coupon flow. Stretch target: diagnose the weak
TEA3 coupon beacon and identify the incidental receipt formatter.
Contrast Set
Compare the two route tests before opening production code:
| Test clue | Same surface shape | Different responsibility path |
|---|---|---|
Successful quote applies STUDY10 |
Calls quoteCheckout() and asserts status/body |
Route → stock check → subtotal → discount |
Out-of-stock items return 409 |
Calls quoteCheckout() and asserts status/body |
Route → stock check → early response |
Same route-test shape, different implementation responsibility. The contrast tells you which helpers to read and which helpers to skip.
Practice mode: on your first attempt, use the +5 min button if you are
still collecting evidence. On a replay, try finishing inside the original
15 minutes. Before the quiz, write one reflection line about what you
inspected first, what you skipped, and what evidence changed or confirmed
your hypothesis.
Do not edit the code. Use a narrow interaction map.
# Backend Interaction Sprint Notes
Contract hypothesis:
Top 3 beacons:
1.
2.
3.
What I can ignore for this question:
Smallest trace:
Central / supporting / incidental files:
Contrast set:
- Same test shape:
- Different runtime paths:
- Helper I can skip for the error path:
Final EiPE summary:
Timer reflection:
- First thing I inspected:
- Detail I deliberately skipped:
- Evidence that changed or confirmed my hypothesis:
const items = [
{ sku: "mochi", name: "Mango Mochi", price: 4, stock: 8 },
{ sku: "ramen", name: "Late-Night Ramen", price: 7, stock: 0 },
{ sku: "tea", name: "Jasmine Tea", price: 3, stock: 15 },
];
module.exports = { items };
const { items } = require("../data/items");
function findItem(sku) {
return items.find(item => item.sku === sku);
}
function checkStock(lineItems) {
const missing = [];
for (const lineItem of lineItems) {
const item = findItem(lineItem.sku);
if (!item || item.stock < lineItem.quantity) {
missing.push(lineItem.sku);
}
}
return { ok: missing.length === 0, missing };
}
function subtotalFor(lineItems) {
return lineItems.reduce((total, lineItem) => {
const item = findItem(lineItem.sku);
return total + item.price * lineItem.quantity;
}, 0);
}
module.exports = { checkStock, subtotalFor };
function discountFor(coupon, subtotal) {
if (coupon === "STUDY10" && subtotal >= 10) {
return Math.round(subtotal * 0.10);
}
if (coupon === "TEA3") {
return 3;
}
return 0;
}
module.exports = { discountFor };
function formatReceiptLine(name, quantity, total) {
return `${quantity}x ${name}: $${total}`;
}
module.exports = { formatReceiptLine };
const { checkStock, subtotalFor } = require("../services/stockService");
const { discountFor } = require("../services/discountService");
function quoteCheckout(req, res) {
const lineItems = req.body?.items ?? [];
const stockReport = checkStock(lineItems);
if (!stockReport.ok) {
return res.status(409).json({
error: "out of stock",
missing: stockReport.missing,
});
}
const subtotal = subtotalFor(lineItems);
const discount = discountFor(req.body?.coupon, subtotal);
return res.json({
subtotal,
discount,
total: subtotal - discount,
});
}
module.exports = { quoteCheckout };
const test = require("node:test");
const assert = require("node:assert/strict");
const { quoteCheckout } = require("../routes/checkoutRoute");
function fakeResponse() {
return {
statusCode: 200,
body: undefined,
status(code) {
this.statusCode = code;
return this;
},
json(payload) {
this.body = payload;
return this;
},
};
}
test("successful quote applies STUDY10 to an eligible subtotal", () => {
const res = fakeResponse();
quoteCheckout({
body: {
coupon: "STUDY10",
items: [
{ sku: "mochi", quantity: 2 },
{ sku: "tea", quantity: 1 },
],
},
}, res);
assert.equal(res.statusCode, 200);
assert.deepEqual(res.body, { subtotal: 11, discount: 1, total: 10 });
});
test("out-of-stock items return 409 and skip totals", () => {
const res = fakeResponse();
quoteCheckout({
body: {
coupon: "STUDY10",
items: [{ sku: "ramen", quantity: 1 }],
},
}, res);
assert.equal(res.statusCode, 409);
assert.deepEqual(res.body, { error: "out of stock", missing: ["ramen"] });
});
Step 5 — Knowledge Check
Min. score: 80%
1. Which helper computes subtotal: 11 for two mochi and one tea?
subtotalFor() reduces line items by looking up each item price and multiplying by quantity.
2. For the out-of-stock request, what is the shortest correct trace?
The relevant branch is route → stock check → early 409 response. A targeted trace stops before discount and subtotal helpers.
3. Where is the STUDY10 coupon applied in a successful quote?
The route passes the coupon and subtotal to the discount helper. The helper owns coupon rules.
4. Which files are part of the runtime flow for a successful checkout quote? (select all that apply)
A successful quote is a runtime flow: route coordination, stock and price helpers, discount rules, and catalog data.
5. When should a reader switch from top-down beacon reading to bottom-up tracing in this example?
Top-down reading is efficient until the evidence gets risky, surprising, or incomplete. Then a short bottom-up trace repairs or confirms the model.
6. A bug report says TEA3 can make tiny orders too cheap. Which explanation best fits the evidence?
Concept location starts from domain language, then false-beacon diagnosis names both the tempting inference and the exact branch that corrects it.
7. You suspect a coupon bug. Which routine move comes first?
Tests-as-specification (Step 2 of Part 2): when a behavior question arises, the contract is in the tests. Reading them first turns ‘what does this code do?’ into the sharper ‘does this code match the contract?’
React Concept Location Sprint
Why this matters
Real comprehension tasks often begin with a domain idea, not a file name: “Where is pinning implemented?” or “Where does completion change?” Concept location is the skill of turning that idea into a focused search path across files. This sprint is larger than the Part 1 React examples, but the goal is still bounded. Treat the timer as a way to notice whether your search path stayed focused.
🎯 You will learn to
- Locate a domain concept across React state, props, and child events
- Rank files as central, supporting, or incidental evidence
- Verify one cross-file interaction with a targeted trace
Reading Goal
You have 10 minutes. Your concept is pinning a lesson.
Read in this order:
App.jsxfor state ownership and derived values.LessonCard.jsxfor the click event.- Only then inspect display-only helpers if a question needs them.
Write a central/supporting/incidental map in reading-notes.md.
| Category | What it means |
|---|---|
| Central | Code that owns or changes the concept |
| Supporting | Code that provides data or displays the concept |
| Incidental | Nearby code that does not participate in the concept |
Stretch target: find one weak beacon. A CSS class like pinned-card can confirm presentation, but it is not enough to prove where pinning state lives.
Practice mode: on your first attempt, use the +5 min button if you are
still collecting evidence. On a replay, try finishing inside the original
10 minutes. Before the quiz, write one reflection line about what you
inspected first, what you skipped, and what evidence changed or confirmed
your hypothesis.
# React Concept Location Notes
Concept:
Central files:
Supporting files:
Incidental files:
Strongest beacons:
1.
2.
3.
Smallest trace:
Final EiPE summary:
Timer reflection:
- First thing I inspected:
- Detail I deliberately skipped:
- Evidence that changed or confirmed my hypothesis:
:root {
--page-bg: #f6f8fb;
--panel-bg: #ffffff;
--text: #172033;
--muted: #526070;
--border: #c7d2df;
--accent: #00598c;
--accent-strong: #00466d;
--button-text: #ffffff;
--pin-bg: #e5f2ff;
--status-bg: #edf7ed;
--focus: #ffbf47;
}
html.dark-mode {
--page-bg: #101827;
--panel-bg: #1d2736;
--text: #f4f7fb;
--muted: #c8d2de;
--border: #516174;
--accent: #7cc7ff;
--accent-strong: #a7dcff;
--button-text: #08111d;
--pin-bg: #1f3850;
--status-bg: #173a29;
--focus: #ffd166;
}
body {
margin: 0;
background: var(--page-bg);
color: var(--text);
font: 16px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.board-shell {
max-width: 920px;
margin: 0 auto;
padding: 24px;
}
.board-shell h1 {
margin-block: 0 18px;
font-size: 1.8em;
}
.filter-label {
display: grid;
gap: 6px;
max-width: 280px;
font-weight: 700;
}
.filter-label select {
min-height: 40px;
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 10px;
background: var(--panel-bg);
color: var(--text);
font: inherit;
}
.progress-summary,
.pinned-status {
border-radius: 8px;
padding: 10px 12px;
background: var(--status-bg);
color: var(--text);
font-weight: 700;
}
.lesson-board-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 14px;
margin-block-start: 18px;
}
.lesson-card {
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
background: var(--panel-bg);
box-shadow: 0 2px 8px rgb(23 32 51 / 0.08);
}
html.dark-mode .lesson-card {
box-shadow: 0 2px 10px rgb(0 0 0 / 0.35);
}
.pinned-card {
border: 2px solid var(--accent);
background: var(--pin-bg);
}
.lesson-card h2,
.lesson-card p {
margin: 0 0 8px;
}
.lesson-card h2 {
font-size: 1.2em;
}
.lesson-card p {
color: var(--muted);
}
.lesson-card button {
min-height: 40px;
min-width: 96px;
margin-inline-end: 8px;
margin-block-start: 6px;
border: 2px solid var(--accent);
border-radius: 6px;
padding: 8px 14px;
background: var(--accent);
color: var(--button-text);
font: inherit;
cursor: pointer;
}
.lesson-card button:hover {
border-color: var(--accent-strong);
background: var(--accent-strong);
}
.board-shell :focus-visible {
outline: 3px solid var(--focus);
outline-offset: 3px;
}
const LESSONS = [
{ id: 1, title: "Python plan roles", topic: "python", done: true },
{ id: 2, title: "React callback descent", topic: "react", done: false },
{ id: 3, title: "Node tests as beacons", topic: "node", done: false },
{ id: 4, title: "Review risk map", topic: "review", done: true },
];
function LessonFilter({ view, onViewChange }) {
return (
<label className="filter-label">
View
<select value={view} onChange={event => onViewChange(event.target.value)}>
<option value="all">All</option>
<option value="open">Open</option>
<option value="done">Done</option>
</select>
</label>
);
}
function LessonCard({ lesson, isPinned, onPinLesson, onCompleteLesson }) {
return (
<article className={isPinned ? "lesson-card pinned-card" : "lesson-card"}>
<h2>{lesson.title}</h2>
<p>Topic: {lesson.topic}</p>
<p>{lesson.done ? "Done" : "Still open"}</p>
<button type="button" onClick={() => onPinLesson(lesson.id)}>
{isPinned ? "Pinned" : "Pin"}
</button>
<button type="button" onClick={() => onCompleteLesson(lesson.id)}>
Mark done
</button>
</article>
);
}
function ProgressSummary({ lessons }) {
const doneCount = lessons.filter(lesson => lesson.done).length;
return (
<p className="progress-summary">
{doneCount} of {lessons.length} lessons complete.
</p>
);
}
function App() {
const [view, setView] = React.useState("all");
const [pinnedId, setPinnedId] = React.useState(2);
const [lessons, setLessons] = React.useState(LESSONS);
function handleCompleteLesson(id) {
setLessons(currentLessons => currentLessons.map(lesson =>
lesson.id === id ? { ...lesson, done: true } : lesson
));
}
const visibleLessons = lessons.filter(lesson => {
if (view === "done") {
return lesson.done;
}
if (view === "open") {
return !lesson.done;
}
return true;
});
const pinnedLesson = lessons.find(lesson => lesson.id === pinnedId);
return (
<main className="board-shell">
<h1>Lesson Board</h1>
<LessonFilter view={view} onViewChange={setView} />
<ProgressSummary lessons={lessons} />
{pinnedLesson && (
<p className="pinned-status" role="status">
Pinned: {pinnedLesson.title}
</p>
)}
<section className="lesson-board-list" aria-label="Visible lessons">
{visibleLessons.map(lesson => (
<LessonCard
key={lesson.id}
lesson={lesson}
isPinned={lesson.id === pinnedId}
onPinLesson={setPinnedId}
onCompleteLesson={handleCompleteLesson}
/>
))}
</section>
</main>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
Step 6 — Knowledge Check
Min. score: 80%1. Where is the pinning state owned?
State ownership is the central evidence for a React concept-location task.
2. A user clicks Pin on a lesson. What is the correct interaction path?
The concept crosses files through a callback prop, then returns to App as derived state and props.
3. Which file is incidental to the pinning concept, even though it is nearby?
Concept-location skill includes knowing what to ignore. Progress counting is real behavior, but it does not implement pinning.
4. Which beacons should appear in a central/supporting map for pinning? (select all that apply)
A good map distinguishes central state and callbacks from supporting presentation.
5. Which explanation best fits the pinning evidence?
Robust top-down reading uses weak cues for orientation, then verifies ownership through state and callback evidence.
6. In App.jsx, what role does the derived value pinnedLesson play?
Variable roles (Part 1, Step 5): derived single-value holders are extremely common in React. Recognizing pinnedLesson as a candidate-shaped value lets you skim past the surrounding && rendering condition with confidence.
Architecture-Code Alignment Review
Why this matters
Advanced comprehension means reading code against an intended architecture, not just finding the line that produces an output. A route, service, data store, and policy helper each have different responsibilities. When those responsibilities stay visible, the code gives future readers trustworthy architectural beacons.
🎯 You will learn to
- Map a Node.js behavior from route to service to data and policy helpers
- Separate specification evidence from runtime implementation evidence
- Evaluate whether files preserve their intended responsibilities
Mini Review Packet
Requirement:
When a student completes a lesson, store the completion, return the completed lesson id, and award a three-day streak badge when the student’s completion days contain a three-day run.
Intended architecture:
| Layer | Responsibility |
|---|---|
| Route | Read HTTP request fields and choose HTTP status/response shape |
| Progress service | Coordinate completion behavior |
| Store | Save and list completion records |
| Badge service | Decide whether the records earn a badge |
| Email preview | Nearby formatting helper, not part of completion behavior |
Read __tests__/progressRoutes.test.js first, then map the requirement to code. Your final answer should name central, supporting, and incidental files.
const completions = [];
function listCompletions(userId) {
return completions
.filter(record => record.userId === userId)
.map(record => ({ ...record }));
}
function saveCompletion(record) {
const alreadySaved = completions.some(existing =>
existing.userId === record.userId &&
existing.lessonId === record.lessonId &&
existing.day === record.day
);
if (!alreadySaved) {
completions.push({ ...record });
}
return { ...record };
}
function resetCompletions() {
completions.length = 0;
}
module.exports = { listCompletions, saveCompletion, resetCompletions };
function streakBadgeFor(records) {
const days = [...new Set(records.map(record => record.day))].sort((a, b) => a - b);
let current = 0;
let previous = null;
for (const day of days) {
current = previous === null || day === previous + 1 ? current + 1 : 1;
if (current >= 3) {
return "three-day-streak";
}
previous = day;
}
return null;
}
module.exports = { streakBadgeFor };
const { listCompletions, saveCompletion } = require("../data/progressStore");
const { streakBadgeFor } = require("./badgeService");
function completeLesson({ userId, lessonId, day }) {
saveCompletion({ userId, lessonId, day });
const records = listCompletions(userId);
return {
completed: true,
lessonId,
badge: streakBadgeFor(records),
};
}
module.exports = { completeLesson };
function previewCompletionEmail(studentName, lessonTitle) {
return `${studentName} completed ${lessonTitle}.`;
}
module.exports = { previewCompletionEmail };
const { completeLesson } = require("../services/progressService");
function completeLessonRoute(req, res) {
const { userId, lessonId, day } = req.body;
if (!userId || !lessonId || !day) {
return res.status(400).json({ error: "missing completion fields" });
}
const summary = completeLesson({ userId, lessonId, day });
return res.status(201).json(summary);
}
module.exports = { completeLessonRoute };
const { beforeEach, test } = require("node:test");
const assert = require("node:assert/strict");
const { listCompletions, resetCompletions } = require("../data/progressStore");
const { completeLessonRoute } = require("../routes/progressRoutes");
function fakeResponse() {
return {
statusCode: 200,
body: undefined,
status(code) {
this.statusCode = code;
return this;
},
json(payload) {
this.body = payload;
return this;
},
};
}
beforeEach(() => {
resetCompletions();
});
test("POST /progress/completions stores a completion and returns 201", () => {
const res = fakeResponse();
completeLessonRoute({ body: { userId: "u1", lessonId: "react-flow", day: 1 } }, res);
assert.equal(res.statusCode, 201);
assert.deepEqual(res.body, {
completed: true,
lessonId: "react-flow",
badge: null,
});
assert.deepEqual(listCompletions("u1"), [
{ userId: "u1", lessonId: "react-flow", day: 1 },
]);
});
test("third consecutive completion returns a streak badge", () => {
completeLessonRoute({ body: { userId: "u2", lessonId: "python-plan", day: 1 } }, fakeResponse());
completeLessonRoute({ body: { userId: "u2", lessonId: "react-flow", day: 2 } }, fakeResponse());
const res = fakeResponse();
completeLessonRoute({ body: { userId: "u2", lessonId: "node-route", day: 3 } }, res);
assert.equal(res.statusCode, 201);
assert.equal(res.body.badge, "three-day-streak");
});
test("missing fields return 400 without storing a completion", () => {
const res = fakeResponse();
completeLessonRoute({ body: { userId: "u3", day: 4 } }, res);
assert.equal(res.statusCode, 400);
assert.deepEqual(res.body, { error: "missing completion fields" });
assert.deepEqual(listCompletions("u3"), []);
});
Step 7 — Knowledge Check
Min. score: 80%1. Which first-pass hypothesis comes from the tests?
The tests provide the specification layer: completion storage, status shape, and streak badge behavior.
2. Where is the missing-field 400 behavior implemented?
The route owns HTTP boundary behavior, including input checks and status/response shape.
3. Which files are central runtime evidence for awarding the streak badge? (select all that apply)
Central runtime files are the ones the successful completion path actually calls.
4. Which responsibility map best matches the implementation?
Architecture-code alignment means the code vocabulary preserves the intended responsibility vocabulary.
5. Which explanation best fits the completion flow?
A plausible nearby file can be a weak contextual beacon. Strong readers verify relevance through imports, calls, and tests.
6. When the intended architecture and the actual code disagree, which artifact is the most reliable tiebreaker?
Tests-as-specification (Step 2 of Part 2): tests are the only executable contract. They run as part of CI and break loudly when behavior drifts. Comments, READMEs, and commit messages cannot do that.
Dashboard Access Sprint
Why this matters
In production code, the first clue that looks relevant is often only part of the story. It may be a file you would expect to matter: featureFlags.js, betaDashboard, imported config, dashboard route. The advanced skill is to say, “That is a plausible hypothesis,” then verify whether the property is actually on the runtime path.
This sprint is a small incident review. A student named Kai cannot see the Labs tab. A fast reader may jump to the global betaDashboard flag because it is true. Your job is to test that hypothesis against tests, imports, and call flow. The timer should expose whether your first path was selective, not push you into guessing.
🎯 You will learn to
- Separate a plausible config clue from the property actually read at runtime
- Use tests as specification beacons without mistaking them for implementation
- Trace a cross-file hypothesis through route, service, policy, and data files
Reading Goal
You have 13 minutes. Read the tests first, then inspect the smallest path that explains Kai’s missing Labs tab.
Focus on these questions:
- What behavior do the tests specify for invited users and non-invited users?
- Which file decides whether the Labs tab is added?
- Which
featureFlagsproperty is read by the route? - Where is
betaDashboard: trueread, if at all, on the tab-building path?
Contrast Set
Compare these similar-looking cues before trusting either one:
| Cue | Same surface shape | Different runtime purpose |
|---|---|---|
featureFlags.welcomeBanner |
Flag-shaped config value | Read by the route to choose banner text |
featureFlags.betaDashboard |
Flag-shaped config value | Present in config, but not read on the Labs-tab path |
user.betaInvite |
Boolean access-looking value | Read by policy and can affect Labs access |
Same surface cue, different purpose. The critical feature is not “looks like a flag”; it is whether the value is read on the runtime path that answers the question.
Practice mode: on your first attempt, use the +5 min button if you are
still collecting evidence. On a replay, try finishing inside the original
13 minutes. Before the quiz, write one reflection line about what you
inspected first, what you skipped, and what evidence changed or confirmed
your hypothesis.
# Dashboard Access Sprint Notes
First hypothesis:
First clue I noticed:
Test evidence:
Runtime path:
Contrast set:
- Same surface cue:
- Runtime purpose that differs:
- Critical feature that explains the difference:
Evidence that changes or strengthens the hypothesis:
Final EiPE summary:
Timer reflection:
- First thing I inspected:
- Detail I deliberately skipped:
- Evidence that changed or confirmed my hypothesis:
const users = [
{ id: "ava", plan: "free", verified: true, betaInvite: true },
{ id: "kai", plan: "free", verified: true, betaInvite: false },
{ id: "mira", plan: "pro", verified: false, betaInvite: false },
{ id: "noor", plan: "pro", verified: true, betaInvite: false },
];
function findUser(userId) {
const user = users.find(candidate => candidate.id === userId);
return user ? { ...user } : null;
}
module.exports = { findUser };
const featureFlags = Object.freeze({
betaDashboard: true,
welcomeBanner: true,
});
module.exports = { featureFlags };
function canUseBetaDashboard(user) {
if (!user || !user.verified) {
return false;
}
return user.betaInvite || user.plan === "pro";
}
module.exports = { canUseBetaDashboard };
const { findUser } = require("../data/users");
const { canUseBetaDashboard } = require("./accessPolicy");
function dashboardTabsFor(userId) {
const user = findUser(userId);
if (!user) {
return { status: "missing", tabs: [] };
}
const tabs = ["overview", "assignments"];
if (canUseBetaDashboard(user)) {
tabs.push("labs");
}
return { status: "ok", tabs };
}
module.exports = { dashboardTabsFor };
const { featureFlags } = require("../config/featureFlags");
const { dashboardTabsFor } = require("../services/dashboardService");
function dashboardRoute(req, res) {
const result = dashboardTabsFor(req.params.userId);
if (result.status === "missing") {
return res.status(404).json({ error: "user not found" });
}
return res.json({
tabs: result.tabs,
banner: featureFlags.welcomeBanner ? "new dashboard preview" : null,
});
}
module.exports = { dashboardRoute };
const test = require("node:test");
const assert = require("node:assert/strict");
const { dashboardRoute } = require("../routes/dashboardRoute");
function fakeResponse() {
return {
statusCode: 200,
body: undefined,
status(code) {
this.statusCode = code;
return this;
},
json(payload) {
this.body = payload;
return this;
},
};
}
test("invited verified student receives the Labs tab", () => {
const res = fakeResponse();
dashboardRoute({ params: { userId: "ava" } }, res);
assert.equal(res.statusCode, 200);
assert.deepEqual(res.body.tabs, ["overview", "assignments", "labs"]);
});
test("global beta flag does not override a missing invite", () => {
const res = fakeResponse();
dashboardRoute({ params: { userId: "kai" } }, res);
assert.equal(res.statusCode, 200);
assert.deepEqual(res.body.tabs, ["overview", "assignments"]);
assert.equal(res.body.banner, "new dashboard preview");
});
test("unknown users receive 404", () => {
const res = fakeResponse();
dashboardRoute({ params: { userId: "unknown" } }, res);
assert.equal(res.statusCode, 404);
assert.deepEqual(res.body, { error: "user not found" });
});
Step 8 — Knowledge Check
Min. score: 80%
1. Kai does not receive the labs tab even though featureFlags.betaDashboard is true. Which hypothesis survives the smallest trace?
The smallest trace is route → dashboardTabsFor() → findUser("kai") → canUseBetaDashboard(). The flag file is imported, but the betaDashboard property is not used on the Labs-tab path.
2. Which evidence best tests whether betaDashboard: true controls Kai’s Labs access?
After the trace, betaDashboard: true is the misleading beacon: the route reads welcomeBanner, while tab access is delegated to dashboardService and accessPolicy.
3. Which files are central runtime evidence for deciding whether labs appears?
(select all that apply)
Central runtime evidence is the code that the route actually calls to build tabs.
4. Which smallest trace best tests the hypothesis that the global beta flag controls Labs access?
The right trace verifies both sides: where Labs is added and whether the tempting flag is part of that path.
5. Which final incident summary is strongest?
The explanation explicitly names the misleading beacon and the correcting evidence: access policy, user data, and absence of betaDashboard from the tab-building call path.
6. In Part 1’s Campus Feed sprint, the pinned field looked decisive but turned out irrelevant to that question. Which verification move generalizes from there to the betaDashboard flag here?
False-beacon discipline (Part 1, Step 7) is the same move here: a true value can be irrelevant if it is not on the runtime path. The fix is the same — grep -r (or ‘who imports this?’) turns ‘beacon I noticed’ into ‘beacon I verified.’
Cross-Domain Reading Boss: Order Inventory Incident
Why this matters
Every earlier step in Part 2 was sized so that a careful linear read could still finish in time. This step is different on purpose. The codebase is around 330 lines across 11 files — a route + four services + two data modules + a decoy route + tests. You cannot read it all carefully during a first-attempt timer and still leave room to answer well.
This is the moment top-down reading was invented for. Production code is rarely the size of a tutorial snippet. Pull requests at real companies routinely exceed what any human can hold in working memory. Reviewers who try to read everything either burn out or rubber-stamp. The routine is what makes the work survivable and the answer correct.
🎯 You will learn to
- Apply the full routine to a Node.js codebase too large to read line-by-line
- Use tests + names + imports to locate a missing call across many files
- Distinguish a function that exists from a function that is on the runtime path
- Combine every prior skill: routine, beacons, variable roles, tests-as-spec, cross-file flow, false-beacon discipline, EiPE
The Incident
An alert from the warehouse this morning:
Customer Devi placed an order for 10 packs of Late-Night Ramen. The API returned
402 Payment Requiredand Devi never received an order confirmation. But when the warehouse pulled inventory at noon, ramen stock had dropped from 12 to 2.
Customer-success traced the call: Devi’s request was well-formed, her available credit was below the calculated total, and the route correctly refused payment with 402. So where did the 10 ramen units go?
The intended behavior, per the engineering doc, is:
“Inventory reservation must be released on every failure path. A failed order must leave inventory exactly as it was before the request.”
Your audit job:
- Where is inventory reservation invoked during an order, and when?
- Why did stock drop by 10 even though no order was created?
- Which file owns the missing behavior, and what specifically is missing?
Time Budget Reality Check
Your first attempt gives you 15 minutes so the clock supports learning instead of panic. Treat 10 minutes as a replay challenge after you already know what a good search path feels like.
| Strategy | Roughly how long it takes |
|---|---|
| Read every file carefully | 25–30 minutes |
| Skim every file | 10–14 minutes |
| Read tests + the order route + one service, focusing on the failure path | 6–9 minutes ← target |
The third strategy is the only one that leaves enough time to think, answer, and write evidence. Hypothesis-driven reading is not a shortcut; it is the only honest path through this much code.
Constraints
- Read at most 3 files carefully.
- Verify any beacon you decide to trust by checking imports or call sites.
- Write your EiPE summary in
reading-notes.mdbefore the timer runs out. - End by writing a timer reflection: what you inspected first, what you deliberately skipped, and what evidence changed or confirmed your hypothesis.
The routine is yours to choose. Let’s see how far you can make it.
# Order Inventory Audit Notes
## Routine
Orient → Predict → Beacon-hunt → Descend selectively → Verify → Summarize
## First hypothesis: which file should own reservation? Which file should call it?
## Files I read carefully (3 or fewer expected)
1.
2.
3.
## Files I deliberately skipped (and why)
## Imports check — which files actually `require("../services/inventoryService")`?
## Final EiPE summary
- Purpose:
- Mechanism:
- Evidence:
- Limit (what I did *not* verify):
## Timer reflection
- First thing I inspected:
- File or detail I deliberately skipped:
- Evidence that changed or confirmed my hypothesis:
const items = [
{ sku: "mochi", name: "Mango Mochi", price: 4, stock: 1 },
{ sku: "ramen", name: "Late-Night Ramen", price: 7, stock: 12 },
{ sku: "tea", name: "Jasmine Tea", price: 3, stock: 30 },
{ sku: "pretzel", name: "Choco Pretzels", price: 5, stock: 8 },
];
module.exports = { items };
const customers = [
{ id: "riley", name: "Riley Park", tier: "standard", credit: 100 },
{ id: "sam", name: "Sam Okafor", tier: "member", credit: 200 },
{ id: "devi", name: "Devi Rao", tier: "member", credit: 50 },
];
module.exports = { customers };
const orders = [];
module.exports = { orders };
const { items } = require("../data/items");
const { reserve, release } = require("./inventoryService");
const carts = new Map();
function getCart(customerId) {
if (!carts.has(customerId)) {
carts.set(customerId, []);
}
return carts.get(customerId);
}
function addToCart(customerId, sku, quantity) {
const item = items.find(entry => entry.sku === sku);
if (!item) {
return { ok: false, reason: "unknown sku" };
}
const reservation = reserve(sku, quantity);
if (!reservation.ok) {
return reservation;
}
const cart = getCart(customerId);
cart.push({ sku, quantity });
return { ok: true, cart };
}
function clearCart(customerId) {
const cart = getCart(customerId);
for (const line of cart) {
release(line.sku, line.quantity);
}
carts.set(customerId, []);
}
module.exports = { getCart, addToCart, clearCart };
const { items } = require("../data/items");
const MEMBER_DISCOUNT_RATE = 0.10;
function lineSubtotal(line) {
const item = items.find(entry => entry.sku === line.sku);
if (!item) {
return 0;
}
return item.price * line.quantity;
}
function subtotalFor(lineItems) {
return lineItems.reduce((sum, line) => sum + lineSubtotal(line), 0);
}
function memberDiscount(subtotal) {
return Math.round(subtotal * MEMBER_DISCOUNT_RATE);
}
function totalFor(customer, lineItems) {
const subtotal = subtotalFor(lineItems);
const discount = customer.tier === "member" ? memberDiscount(subtotal) : 0;
return { subtotal, discount, total: subtotal - discount };
}
module.exports = { subtotalFor, memberDiscount, totalFor };
const { items } = require("../data/items");
function availableFor(sku) {
const item = items.find(entry => entry.sku === sku);
return item ? item.stock : 0;
}
function reserve(sku, quantity) {
const item = items.find(entry => entry.sku === sku);
if (!item) {
return { ok: false, reason: "unknown sku" };
}
if (item.stock < quantity) {
return { ok: false, reason: "insufficient stock", available: item.stock };
}
item.stock -= quantity;
return { ok: true, reserved: quantity, remaining: item.stock };
}
function release(sku, quantity) {
const item = items.find(entry => entry.sku === sku);
if (item) {
item.stock += quantity;
}
}
module.exports = { availableFor, reserve, release };
const { customers } = require("../data/customers");
function chargeCustomer(customerId, amount) {
const customer = customers.find(entry => entry.id === customerId);
if (!customer) {
return { ok: false, reason: "unknown customer" };
}
if (customer.credit < amount) {
return { ok: false, reason: "insufficient credit" };
}
customer.credit -= amount;
return { ok: true, charged: amount, remainingCredit: customer.credit };
}
module.exports = { chargeCustomer };
const sentEmails = [];
function sendOrderConfirmation(customerId, order) {
const body = `Order ${order.id} confirmed for ${customerId}.`;
sentEmails.push({ to: customerId, body });
return { sent: true };
}
function sentEmailsFor(customerId) {
return sentEmails.filter(email => email.to === customerId);
}
module.exports = { sendOrderConfirmation, sentEmailsFor };
const { addToCart, clearCart } = require("../services/cartService");
function addItemRoute(req, res) {
const { customerId, sku, quantity } = req.body || {};
const result = addToCart(customerId, sku, quantity);
if (!result.ok) {
return res.status(409).json({ error: result.reason });
}
return res.status(201).json({ cart: result.cart });
}
function clearCartRoute(req, res) {
clearCart(req.params.customerId);
return res.status(204).json(null);
}
module.exports = { addItemRoute, clearCartRoute };
const { customers } = require("../data/customers");
const { orders } = require("../data/orders");
const { totalFor } = require("../services/pricingService");
const { chargeCustomer } = require("../services/paymentService");
const { reserve, release } = require("../services/inventoryService");
const { sendOrderConfirmation } = require("../services/notificationService");
function nextOrderId() {
return `o${orders.length + 1}`;
}
function reserveAllLines(lineItems) {
const reservations = [];
for (const line of lineItems) {
const result = reserve(line.sku, line.quantity);
if (!result.ok) {
for (const prior of reservations) {
release(prior.sku, prior.quantity);
}
return { ok: false, reason: result.reason, sku: line.sku };
}
reservations.push({ sku: line.sku, quantity: line.quantity });
}
return { ok: true, reservations };
}
function createOrderRoute(req, res) {
const { customerId, lineItems } = req.body || {};
const customer = customers.find(entry => entry.id === customerId);
if (!customer) {
return res.status(404).json({ error: "unknown customer" });
}
const reservation = reserveAllLines(lineItems);
if (!reservation.ok) {
return res.status(409).json({ error: reservation.reason, sku: reservation.sku });
}
const pricing = totalFor(customer, lineItems);
const payment = chargeCustomer(customerId, pricing.total);
if (!payment.ok) {
return res.status(402).json({ error: payment.reason });
}
const order = {
id: nextOrderId(),
customerId,
lineItems,
subtotal: pricing.subtotal,
discount: pricing.discount,
total: pricing.total,
status: "confirmed",
};
orders.push(order);
sendOrderConfirmation(customerId, order);
return res.status(201).json(order);
}
module.exports = { createOrderRoute };
const test = require("node:test");
const assert = require("node:assert/strict");
const { createOrderRoute } = require("../routes/orderRoute");
const { items } = require("../data/items");
function fakeResponse() {
return {
statusCode: 200,
body: undefined,
status(code) { this.statusCode = code; return this; },
json(payload) { this.body = payload; return this; },
};
}
test("known customer with valid items receives 201 and an order id", () => {
const res = fakeResponse();
createOrderRoute(
{ body: { customerId: "riley", lineItems: [{ sku: "tea", quantity: 1 }] } },
res,
);
assert.equal(res.statusCode, 201);
assert.ok(res.body.id.startsWith("o"));
assert.equal(res.body.status, "confirmed");
});
test("unknown customer returns 404", () => {
const res = fakeResponse();
createOrderRoute(
{ body: { customerId: "ghost", lineItems: [{ sku: "tea", quantity: 1 }] } },
res,
);
assert.equal(res.statusCode, 404);
});
test("insufficient credit returns 402", () => {
const res = fakeResponse();
createOrderRoute(
{ body: { customerId: "devi", lineItems: [{ sku: "ramen", quantity: 10 }] } },
res,
);
assert.equal(res.statusCode, 402);
});
Step 9 — Cross-Domain Reading Boss
Min. score: 80%1. Given the time budget, which reading strategy best fits this incident?
When the bug report is about a side effect on a failure path, the routine focuses on those two things: which side-effects this handler is supposed to manage, and what its failure branches do with them. Status codes alone never answer that.
2. Why did Devi’s 402-failed request leak 10 units of ramen stock?
Classic missing-compensation bug. The route correctly rolls back partial reservations within the reservation loop (good!) but forgets to release reservations on the payment-failure path. The right helper (release) exists, is even imported into the route, and the author used it once — they just didn’t use it everywhere they should have.
3. Classify each file. Which are CENTRAL evidence for this incident? (select all that apply)
For a missing-compensation bug, the central evidence is: (a) the failure branch that forgot to compensate, (b) the helper it should have called, and (c) the test that should have caught it but didn’t.
4. Why don’t the existing tests in __tests__/orderRoute.test.js catch Devi’s bug?
Tests-as-spec is powerful but bounded. The 402 test verifies status code, never side-effects. A regression test that read ramen.stock before and after the call (or asserted it was unchanged on a failed request) would have caught this immediately. The same lesson as Step 9 of Part 1’s boss: tests pin what they assert, not everything you might want.
5. In reserveAllLines(), what role does the local reservations array play?
Recognizing reservations as a running record for rollback is exactly what makes the bug visible: this pattern works inside the loop (partial reservations get released), but the same compensation logic is missing on the payment failure path, where there’s no analogous variable carrying state across the failure.
6. Seeing reserve and release exported as a pair from inventoryService.js is which kind of beacon for an order-route reviewer?
When you see acquire/release, lock/unlock, reserve/release, open/close, that pairing IS the beacon: it tells the reader ‘this resource is acquired and must be released on every exit path.’ The bug is the absence of release on one of those exit paths.
7. Which final EiPE explanation best fits the evidence?
A strong final summary names the exact missing call (release in the payment-failure branch), distinguishes the reservation-failure branch (which does compensate) from the payment-failure branch (which doesn’t), and is honest about whether the audit covered every failure path. EiPE without the Limit line is overconfident; with it, this is the kind of incident summary that earns reviewer trust.