You used an AI coding tool to build a feature. The list appears, the filters work, and another prompt can change the result. Then someone asks why one item disappeared, or whether a small rule change will affect the other filters. You have to ask the AI again.
Try a small JavaScript filter. Write down which items it will keep, change the stock threshold by hand, then run it and compare the result with your prediction.
Choose a behavior you can predict
“Teach me this entire app” is a large task. Choose a result you can name instead: which items remain when a category, search text, and availability switch are combined?
Try three questions before making changes:
- Which item IDs should this input return?
- Which condition includes or excludes each item?
- If the availability rule changes, which of those results should stay the same?
If you cannot yet read the syntax, work through one expression at a time. In this exercise, filter keeps items whose callback returns true, && requires all the conditions to pass, and || lets either side satisfy a condition. The input and output are small enough to work out on paper.
Download the filter learning lab. The code and four records were constructed for this lesson; they are not a captured AI response or a real application’s source. Unzip it and open filter-learning-lab. You need Node.js 22 or later, a text editor, and a terminal. There are no dependencies to install, model calls, or network requests.
Write three predictions before running the code
Read catalog.mjs and filter.mjs. The catalog contains these records:
| ID | Label | Category | Stock |
|---|---|---|---|
folded-stars |
Folded stars | paper |
1 |
paper-kites |
Paper kites | paper |
3 |
clay-moons |
Clay moons | clay |
0 |
clay-bells |
Clay bells | clay |
2 |
The original availability rule includes an item when it has at least one unit. The search uses the label, ignores letter case, and trims whitespace around the query. Category, search, and availability must all match. Category all accepts any category; an empty search matches any label.
Open blank-note.md and write the expected IDs for these inputs. Read the function as you need to, but hold off on running the observer or asking for the answer.
| Case | Category | Search | availableOnly |
What to explain |
|---|---|---|---|---|
| A | paper |
empty | true |
Why a stock of 1 still qualifies |
| B | all |
CLAY |
false |
Why the zero-stock item can appear |
| C | clay |
bells |
true |
How all three conditions combine |
Then run these commands from the extracted folder:
node observe.mjs
node --test baseline.test.mjs
Compare your predictions with the original results
| Case | Original IDs | Reason |
|---|---|---|
| A | folded-stars, paper-kites |
Both are paper and both have stock of at least 1. |
| B | clay-moons, clay-bells |
The trimmed, case-insensitive label search matches both. Availability filtering is switched off. |
| C | clay-bells |
It matches the category and label, and its stock is 2. |
When your prediction differs, mark the first condition you misunderstood. For case B, “the item is in stock” would be the wrong explanation: clay-moons has zero stock. It remains because availableOnly is false, so that condition does not exclude it.
Explain the rule without borrowing an answer
Close the completed note if you opened it. Write two or three sentences that explain case B to someone looking at the catalog. Include the actual input and the condition that makes zero stock acceptable.
Keep the small set of files and their jobs separate:
| File | Its job in this exercise |
|---|---|
catalog.mjs |
Supplies the four records. |
filter.mjs |
Decides which records match the supplied conditions. |
observe.mjs |
Supplies three sets of conditions and prints selected IDs and stock. |
baseline.test.mjs |
Checks the original filtering behavior. |
The observer is a terminal caller, not a browser screenshot. In your own app, a button or form may supply the same kinds of values; read that caller before assuming what the user interface sends.
You can use Yenpo’s local code reader to keep the data, filter, and caller open while you read. File and text search do not need a model connection. If you use the AI Reader with your own provider, ask about the specific condition you are stuck on, then return to the surrounding source and write your own explanation. Run the commands yourself in Terminal; this exercise needs no model response.
Change one rule by hand
Now change the requirement: when availability filtering is on, show only materials with enough stock for two people, one unit each. Keep category filtering, search normalization, and the off state of the availability switch unchanged.
The original “at least one” rule was correct for the original requirement. This is a small feature change, not a hidden bug fix.
Before editing, write another prediction. Case A should lose folded-stars. Case B should still include the zero-stock record because the switch is off. Case C should keep clay-bells, whose stock is exactly 2.
Run the new requirement’s checks once against the original code:
node --test exercise/pair-policy.check.mjs
This command is expected to fail before the edit: the downloaded function still accepts stock of 1. Read the failed assertion to see which requested behavior has not been implemented. A syntax error or missing file would be a different failure.
In filter.mjs, change only the stock threshold from >= 1 to >= 2. Keep the availableOnly condition around it. Then run:
node observe.mjs
node --test exercise/pair-policy.check.mjs
| Case | IDs after the edit | What this checks |
|---|---|---|
| A | paper-kites |
One unit no longer meets the selected two-person rule. |
| B | clay-moons, clay-bells |
Switching availability off still bypasses the stock rule; search still trims and ignores case. |
| C | clay-bells |
Exactly two units qualifies; changing to > 2 would get this wrong. |
The original baseline suite describes the one-unit rule. Its affected assertions will fail after this intentional requirement change. Use the separately named two-person checks for the new behavior; do not erase an assertion merely to hide a failure. The archive keeps the original source so you can repeat the exercise from the beginning.
Explain the change again, including what stayed the same
Put the completed example aside and finish your note in your own words. It should identify:
- The original and new stock thresholds, and the exact place you changed.
- Why case A loses one item while case B is unchanged.
- Why stock of exactly 2 must still qualify in case C.
- The commands you ran and what their outputs showed.
- What you have not checked, such as a real app’s form inputs, server behavior, or persistence.
A useful final explanation is specific: “With availability on, all filters must match and stock must now be at least two. With it off, stock does not affect selection. The changed threshold removes folded-stars from A, while B and C keep the same IDs.” Close the page and try saying that from the code rather than memorizing this wording.
Now try a different input. Predict its result before running it, then explain which conditions kept or removed each item.
Use the same cycle on one feature in your project
Choose a small behavior with visible inputs and an output you can reproduce. Record the source version, make a copy or use your normal version-control workflow, and keep the first edit narrow. Write the predicted result before running it. When the result differs, read the relevant condition and caller before requesting another generated patch.
If you cannot locate the behavior yet, start with finding an entry in unfamiliar code. If your task is to decide whether an AI explanation is true, use the explanation-checking exercise. If you are reviewing a proposed change, the promise-cache walkthrough works through one concrete patch and its failure case.