1. What a log is
Tommy really wants to tell the agent, “something is wrong with the score in the game, fix it.” But he stops himself—Alex has drilled in a discipline: the thought “something is off” is not input for a fix. You need evidence. And, as Alex says, the evidence comes from the log. It’s a familiar word, but Tommy doesn’t really know what it means—and he catches Oliver, who happens to be walking by.
— Uncle Oliver, so what is a log anyway? That giant scroll I always drag around and close?
— He’s the one who closes the scroll, — Oliver snorts and stops. — A log is the program’s diary. As it runs, it records what it does: it started here, calculated there, stumbled over there. Like an airplane’s black box—it writes everything down so that later, if something goes down, there’s something to investigate.
— And where do you look at this diary?
— Well, that can vary, — Oliver counts off on his fingers. — Sometimes the program writes the log to a file on disk—then it stays there afterward, and you can open it even tomorrow. Remember your nightly journal that survived a crash? That’s a log in a file. And sometimes it writes to the console—straight into the black terminal window, right there in front of you. Tests, for example, shout to the console: run them, and you immediately see what came out. File or console—the essence is the same: the program itself tells you what is happening to it.
Tommy nods. The annoying scroll in his head stops being a scolding and turns into a diary: if the program itself recorded where it stumbled, then that is where the problem is.
2. Test log and crash log—don’t mix them up
— Just keep in mind, — Oliver adds, — today you have two different logs, and you shouldn’t mix them up.
He shows it on his fingers.
— First is the test log. That’s when your checker reported back: it expected three, got thirty, and that’s a FAIL. It’s the report from the checker—what it checked and what didn’t match. The second is the crash log, more formally the stack trace, the “trace of the call stack.” That’s when the program itself stumbled and recorded where in the code it blew up. The checker says “the result is wrong,” while the stack trace says “it blew up right on this line.” Different things: one is about the outcome, the other is about the location.
— So which one do I need?
— Right now, the second one—the one that points to the line. So you don’t have to guess where to fix it. Though it’s handy when a test prints both at once: “wrong result” and “here’s where.” I’ll find a couple of examples of my own and show you.
3. The stack trace leads to the exact line
While Oliver looks for suitable examples, Alex jumps into the conversation. First we reproduce the bug, so the game itself writes about the problem. We run the tests and catch the failure:
npm test
✖ three in a row give 3 points (1 per match)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
30 !== 3 ← got 30, expected 3
at TestContext.<anonymous> (src/bonus-game/score.test.js:8:10) ← the test line where it didn’t match
— See, here are both things at once that Oliver was talking about, — Alex points at the output. — The top part, 30 !== 3 (got thirty, expected three), is the test log: the checker reported back that the values didn’t match. And the bottom part, at … (src/bonus-game/score.test.js:8:10), is the trace: the exact address of the line where the check failed. src/bonus-game/score.test.js is the file. 8 is the line. 10 is the character. Go there and look at WHAT exactly was being checked.
Tommy opens score.test.js, line 8—and there it is, all written out: assert.equal(calcScore(3), 3). The test called the calcScore function and expected a three from it.
— So the log gave me both the symptom and the address, — Tommy leans toward the screen. — “Thirty instead of three” is the checker, and the test line names the culprit: calcScore. Not a wall of text, but a ladder: the log leads to the test, the test leads to the function.
That same “scary scroll” he had been dragging around and closing without looking at for weeks is, right before his eyes, turning into a map. Before, he looked at the log like it was scolding him and he just had to wait it out. Now he reads it like an address: house, floor, apartment.
Tommy opens src/bonus-game/score.js and scrolls down to calcScore—not by guessing across the whole project, but straight to where the ladder led him. Finger on the wheel, line 7, 8, 9.
There it is.
Line 9: each match is multiplied by the constant POINTS_PER_MATCH—and there it is, higher up in the file: POINTS_PER_MATCH = 10. But it should be 1. One digit. Three matches instead of “plus three points” give “three times ten points”—that’s where the steady thirty he kept catching in the game all morning came from.
— You’ve got to be kidding me, — Tommy exhales. — This whole smug little arcade that smiled at me and lied—that’s just one digit?
He’s even a little disappointed that it was that simple. The root cause wasn’t guessed, wasn’t beaten out by poking through files—it was found with his eyes from the log in a minute.
— And notice, — Alex adds, — we didn’t guess a single line. The log itself led us from the symptom to the line. That’s why you don’t just scroll past it and close it—you read it.
— And now for the trick, — Alex continues. — You don’t keep this log in your head and retell it to the agent in your own words. You hand over the evidence itself. Look at the difference.
❌ like this: points in the game are counted wrong, take a look and fix it
✅ like this: bug in calcScore (src/bonus-game/score.js:9): 3 matches give 30 instead of 3,
constant POINTS_PER_MATCH=10 instead of 1. Stack trace: [log inserted].
Fix the cause, don't touch neighboring parts of the game.
— Feel the difference in the input data? — Alex is pleased. — In the first case the agent will go poking around at random, might end up fixing rendering or rewrite the wrong module. In the second case, it has an exact piece of evidence, and it fixes the right place. Give it emotion—and you get guesses. Give it evidence—and you get work done properly.
Tommy goes back to his spec and rewrites the defect line. In the morning he wrote it vaguely: “the scoring logic is lying.” Now the same line has been tightened to something exact—file, function, line, cause:
# this is what it looked like in the morning:
DEFECT: 3 in a row awards 30 points instead of 3 (scoring logic is wrong)
# after the log:
DEFECT: calcScore (src/bonus-game/score.js:9) — POINTS_PER_MATCH=10 instead of 1:
3 matches → 30 points instead of 3
Not “something is wrong with the score,” but file-function-line-cause. The more precise the input, the less chance the agent will go fix the wrong problem.
4. Design the check for the specific bug
Before calling the agent to fix it, Alex writes down a second important thought—and it’s about HOW to verify it.
— Look, — he says. — Tests come in all kinds. In a project there are usually tons of them—for different cases. And it’s easy to fall into a trap: “I’ll just run everything, maybe it’ll all turn green.” You run the whole pile, see the overall “everything passed,” and feel calm.
— What’s wrong with that? If I ran everything, then everything was checked.
— Not necessarily. Among all those tests there may simply not be a test for your bug. You ran a hundred unrelated checks, they all went green—and none of them even looked at your thirty-instead-of-three case. You got excited about green, but it was about something else. So the professional approach is different: not “run whatever exists,” but make a check specifically for your bug.
— Meaning?
— Here, look at the difference. — Alex spreads his fingers. — Childishly, it would be like: “well, I’ll run the tests, see if they’re green.” Any tests, in bulk. But as an adult, you first ask yourself: which exact test will catch THIS failure? Your bug is three in a row gives thirty. So you need a test that checks exactly that: “give the score three in a row, expect exactly three.” You named it, you know what it catches. And if IT is green, then that’s about your bug, not about a hundred neighboring ones.
Tommy nods—now it’s clearer. The check is not “run it at random,” but designed for the goal: you know what you are checking, you know what the correct answer is. Like writing a spec for a task, not “do something.”
— Got it? — Alex can tell it’s not fully landing yet. — Fine, words are words. Now you’ll see for yourself why this matters. We’ll call the agent to fix it; it’ll bring you a green test, all neat and proper. And after that I’ll show you one thing that will make you stop buying into plain “green.” Then you’ll understand why a check has to be built with your head, not run in bulk.
Tommy shrugs and goes to call the agent. Whatever that thing is—we’ll see.