Guide
When zero is a valid limit
A default can hide a valid value. Here, a caller asks for zero items and gets three. Run the failing test, try a correction that still fails, then check the fix against the same tests.
This is a deliberately small exercise run for this guide, not a historical project incident. You can reproduce it by hand or use it to practise checking an assistant’s diagnosis.
Get the exercise
You need Node.js 24 and a terminal. No dependencies to install, service, account or paid model is needed.
Download the exercise ZIP · Browse the offline guide · Verify the download
Unzip it into a new folder, then open a terminal in worked-example/. If you already have the repository, use examples/array-limit/.
node --version
node --test-reporter=tap test.cjs buggy
node --test-reporter=tap test.cjs attempt
node --test-reporter=tap test.cjs fixed
Run each stage separately. The first two commands deliberately exit with code 1. Do not chain them with &&, which would stop at the first failure. The fixed stage should exit with code 0.
1. Make the failure visible
The contract is small: an omitted or null limit means three; zero means none; a positive integer caps the result. The function returns a new array.
// Contract: null/undefined use 3; zero returns no items; positive integers cap results.
module.exports = function take(items, limit) {
return items.slice(0, limit || 3);
};
The same six tests run against every stage. With ["oak", "ash", "elm", "beech"] and a limit of zero, the test expects [] but the original returns ["oak", "ash", "elm"]. || treats zero as false and selects the default.
2. Check the attempted correction
// Attempt: move the default into a variable. Zero is still treated as false.
module.exports = function take(items, limit) {
const count = limit ? limit : 3;
return items.slice(0, count);
};
Moving the default into a variable looks plausible. The condition still treats zero as false, so the zero test still fails. A changed implementation is not enough to show that the problem is fixed.
3. Preserve zero and verify
module.exports = function take(items, limit) {
const count = limit ?? 3;
return items.slice(0, count);
};
?? selects the default only for null or undefined. Zero reaches slice unchanged. The other tests check the defaults, positive and large limits, empty input and that the input stays unchanged.
Actual run
Run for this guide on 15th October 2026 with Node 24.21.0. These are the test counts and exit codes from that run; timings and stack paths depend on your machine.
| Stage | Pass | Fail | Exit |
|---|---|---|---|
| buggy | 5 | 1 | 1 |
| attempt | 5 | 1 | 1 |
| fixed | 6 | 0 | 0 |
What this proves
You can reproduce a specific failure, see why an attempted correction leaves it in place, and verify a fix against a stated contract. The six tests cover this function. A real API also needs a policy for invalid limits, such as negative numbers, fractions or strings, and checks in the project where it will run.
Try the diagnosis with your host
Ask: “Read test.cjs and buggy.cjs. Explain why zero fails, cite the relevant lines and suggest a focused check. Do not edit files.” Check the answer against the source. If you then want to practise editing, explicitly ask for a local correction and rerun the tests.
Try the first-hour setup · Agents: get going · Read the engineering stories
If a step does not work, tell us which step and what happened.
(Briar helped draft this)