Every word

526 words, in the order the course teaches them. Press / anywhere to describe one you can’t name.

1. The machine

Source code
The text of a program, written by a person or an agent and saved in ordinary files. It is a precise set of instructions. The computer does what the text says, which is not always what its author meant.
Program
A set of instructions a computer can carry out. Your browser is a program, and so is the agent you talk to. A program sits in a file doing nothing until something starts it.
Files and folders
A file is a named chunk of data kept on a computer. A folder, also called a directory, is a named container for files and other folders, so everything on the machine forms one big tree.
Code editor
A program for opening and changing plain text files, made for code. It colours the text so the structure stands out, shows the project's folders down one side, and marks some mistakes as you type. VS Code is a common one.
CPU and memory
The CPU is the part that carries out instructions, one tiny step at a time, very fast. Memory, or RAM, is the quick short-term space where a running program keeps its instructions and the values it is working on.
Disk
Long-term storage, where files stay when the power goes off. It is much slower than memory. A program that only keeps data in memory loses it when it stops, crashes or the machine restarts.
Process
One running copy of a program, with its own private memory and an ID number called a PID. Start a program twice and you have two processes that know nothing about each other. Each runs until it finishes or something stops it.
Terminal
A window where you control a computer by typing instead of clicking, and it answers in text. It looks old-fashioned, but nearly every tool a programmer uses can be driven from it.
Shell
The program inside the terminal that reads your line, works out what you mean, starts the right programs and shows you the result. Common ones are bash and zsh. It can also join programs together, and that is most of its power.
Command
One line you give the shell: the name of a program, then flags that change how it behaves, then arguments saying what to work on. In rm -r build, rm is the program, -r is a flag and build is the argument. Spaces separate the pieces.
Path
The written address of a file or folder. An absolute path starts from the top, as in /home/you/notes.txt, and means the same everywhere. A relative path, as in src/cart.js, starts from where you are. .. means the folder above and ~ means your home folder.
Working directory
The folder a shell is standing in right now. Relative paths start from here. pwd prints it and cd changes it. Every process has its own, so a cd inside a script doesn't move the shell you started it from.
Environment variable
A named setting a process carries with it, such as TZ=Europe/London for its time zone. A program can read it without it being in the code, and passes a copy to any program it starts. A child can't change its parent's copy.
The PATH variable
An environment variable holding a list of folders. When you type a program's name, the shell looks through those folders in order and runs the first match. If none has it, you get command not found, even when the program is on the machine.
Exit code
The number a program hands back when it ends. 0 means it went fine, and anything else means it didn't. You rarely see it, but the shell keeps the latest one in $?. Automatic checks in software rest on this.
stdin, stdout and stderr
Three channels every process starts with. Stdin is what comes in. Stdout is its results. Stderr is for errors and remarks. On screen, stdout and stderr look alike, but they are separate and can each be sent somewhere different.
Redirection
Sending a stream somewhere other than the screen. > writes stdout to a file, replacing what was there, and >> adds to the end. 2> does the same for stderr. 2>&1 sends stderr wherever stdout is going. /dev/null throws away whatever reaches it.
Pipe
The | character. It feeds one program's stdout into the next program's stdin, so small tools combine: grep ERROR app.log | sort | uniq -c finds lines, sorts them and counts repeats. By default, the whole line reports only the last program's exit code.
File permissions
Rules saying who may read, write and run each file. ls -l shows them as -rwxr-xr--: three letters for the owner, three for a group, three for everyone else. chmod changes them. root, the administrator account, ignores most of them.
Programming language
A strict, made-up notation for writing instructions. Python, JavaScript, TypeScript, Go and Rust are all programming languages. Each has exact rules, so a missing bracket is not a typo to read past. It is a program that won't run.
Compiler
A program that reads all your source code and translates it into a form a machine can run. If anything is broken, it refuses and produces nothing. Go, Rust and C are compiled. TypeScript's compiler, tsc, checks each value is the right kind and writes JavaScript.
Interpreter and runtime
An interpreter runs source code directly, working through it as it goes, so many problems only appear when reached. A runtime is what a program needs around it while running. Python, Node.js and Bun are examples. The line with compilers is blurry.
Package manager
A program that downloads code other people have published, from a public store called a registry, and keeps track of what you use. npm, pnpm and Bun do this for JavaScript, and pip and uv for Python. You run it in the terminal like anything else.
Dependency
Code your project relies on but didn't write. The ones you name, in a file called package.json for JavaScript, are direct. They have dependencies of their own, and those have theirs, so these transitive ones are usually most of what you install, into a folder called node_modules.
Lockfile
A file the package manager writes, recording the exact version of every dependency it installed and a fingerprint of its contents. It means everyone, and every automated run, installs the same code. Don't write it by hand, but do keep it in the project.
Script
A text file of commands that run in order, so what you would type by hand happens the same way every time. Projects also give short ones names in package.json, which is what bun run check means. A shell script has to be told to stop at a failure.
Operating system
The program that runs the machine: it shares out the CPU and memory, keeps files on the disk, and starts and stops processes. macOS, Linux and Windows are operating systems. Programs ask it for everything, so a program built for one often won't run on another.
Binary and bytes
Computers store everything as bits, each one 0 or 1. Eight bits make a byte, which can hold 256 different values. Text, pictures and programs are all runs of bytes, and only the reader decides what they mean.
Text encoding
The rule for turning characters into bytes and back. UTF-8 is the usual one today: English letters take one byte, é takes two and 日 takes three. Read with the wrong rule, the same bytes come out as garbage, such as café for café.
Your first agent
A coding agent is a program you install and then start in a terminal, from inside a project's folder. It reads and changes what is there and runs commands, usually asking you first. A project is only a folder, so a new empty one will do.

2. The network

Client and server
A client asks and a server answers. A server is only a program on a computer somewhere, waiting to be asked. Your browser is a client. So is a phone app, or a script you run in a terminal.
Browser
The program that turns an address into a page. It asks servers for files, draws what comes back, and runs the code that came with it. Chrome, Safari and Firefox are browsers.
Frontend and backend
The frontend is the code that runs in the user's browser. The backend is the code that runs on your server. Anyone can read the frontend and change what it sends. Nobody outside can read the backend.
URL
The address of one thing on the web. https://shop.example.com:443/cart?coupon=SAVE#total has a scheme, a host, a port, a path, a query and a fragment. Each part is read by something different.
DNS
The internet's address book. It turns a name like shop.example.com into the numeric address of a computer. Answers get saved along the way, and each one says how long it may be kept, which is called its TTL.
IP address and port
An IP address identifies a computer on a network, like 203.0.113.10. A port number picks out one program on that computer, because many can be listening at once. Together they say exactly where a message goes.
Localhost
A name that always means this same computer. A server on localhost:5173 answers you and nobody else, because for anyone else the same name means their own machine.
TCP connection
A reliable conversation between two programs across a network. Before any data moves, the two sides exchange messages to open the connection, and that costs one full trip there and back.
HTTP
The agreed format browsers and servers use to talk. One side sends a request, the other sends back a response. It remembers nothing between requests, so each one has to carry everything the server needs to know.
Request and response
A request is a method (a verb such as GET), a path, some headers (labelled lines of extra information) and maybe a body (the content). A response is a status code (a number saying how it went), some headers and maybe a body. Every feature on the web is built from those two shapes.
curl
A command that sends one HTTP request from the terminal and prints what comes back. It takes the browser out of the question, so it tells you whether the server itself works.
HTTP method
The verb at the start of a request. GET reads, POST creates or submits, PUT replaces, DELETE removes. The method also tells everything between you and the server whether it's safe to send the same request again.
Status code
A three-digit number at the top of every response. 2xx means it worked, 3xx means look elsewhere, 4xx means the request was wrong, and 5xx means the server failed. It works like an exit code for the web.
Header
A labelled line of extra information on a request or response, such as Content-Type: application/json. Names ignore upper and lower case. Many travel with every request, and you never see them unless you look.
JSON
A plain text format for data: named values in curly braces (called objects), lists in square brackets, text in double quotes, plus numbers, true, false and null, which means nothing. Most programs on the web send it. Nothing else is allowed, including comments.
API
The set of requests a program agrees to answer, and the answers it promises to give. It's a contract between two pieces of software, so that neither side has to read the other's code.
REST
A style of designing web APIs around things rather than actions: GET /orders/42, not POST /getOrder. The word comes from Roy Fielding's 2000 dissertation, and most APIs called REST follow only part of it.
Database, briefly
A program whose whole job is keeping data safe on disk and finding it again quickly. Your server sends it questions over a connection. When your server restarts, its memory is gone, and the database still has everything.
Cookie
A small piece of text a server asks the browser to keep. The browser then attaches it to later requests to that site, by itself. It's how HTTP, which has no memory, comes to know you.
Login session
The server's memory of a signed-in user. At login it creates a record and gives the browser a long random id in a cookie. Each later request carries the id, so the server can look up who it belongs to.
HTTPS and TLS
HTTPS is HTTP sent through TLS, an encrypted tunnel. TLS proves you reached the real site, hides what you send, and detects any change on the way. A padlock means the line is private, and says nothing about whether the site is honest.
The life of a request
One click travels through a DNS lookup, a connection, encryption, your server, your database and back. Each step takes time, and they add up. A latency budget says how long the whole trip may take, so you can see which step broke it.
Caching in the browser and on the way
A saved copy of a response, kept by the browser or by something between you and the server, so the same request needn't travel again. The Cache-Control header sets the rules. It makes sites fast, and it's why people see old versions.
CDN
A network of servers around the world that keep copies of your files close to users. Requests go to the nearest one, and only a miss has to travel on to your real server, which is called the origin.
Reverse proxy
A server that stands in front of your real server, takes requests from outside and passes them on. It can handle encryption, share load between copies and cut off slow replies, so "the server" is usually several programs.
WebSocket
A connection that stays open, so either side can send at any moment. It starts as an ordinary HTTP request, and then both sides agree to switch. Plain HTTP can't do this, because there the server only ever answers.
Webhook
A request another company's server sends to yours when something happens, such as a payment clearing. It's an API call the other way round: you give them a URL and wait. Anyone who finds that URL can send to it too.
Framework
A large body of code that makes most of the structural decisions for you, such as how a URL finds its code and where files go. You fill in the gaps. Next.js, Rails, Django and Laravel are frameworks.
HTML, CSS and JavaScript
The three languages a browser understands. HTML says what's on the page, CSS says how it looks, and JavaScript says what it does. Whatever tools an agent uses, these are what finally reach the browser.
Server and client rendering
Rendering means turning data into a page. Server rendering does it before sending, so the HTML arrives ready to read. Client rendering sends JavaScript that builds the page in the browser. Static rendering does it once, when the site is built.
Timeout
A limit on how long to wait for something before giving up and reporting failure. Without one, a program waiting on a server that never replies can wait for ever, holding on to everything it was using.

3. Version control

Version control
A system that keeps every saved version of a project, with who changed what and when, so you can compare any two versions or go back to one. Git is the one this course uses, and the one you will keep meeting.
Repository
One project under version control: your files, plus a hidden folder called .git that holds the entire history. Run git init in a folder and it becomes a repository. Delete .git and the history is gone.
Commit
A saved snapshot of the whole project, with a message, an author, a time, and a link to the commit before it. Its name is a hash: a long fingerprint worked out from all of that, so identical contents always get the same name.
Diff
A list of exactly what changed between two versions: the lines removed, the lines added, and a few around them for context. Removed lines start with a minus sign and added lines with a plus.
Staging area
A holding area between your files and the next commit. git add puts a copy of a file there, exactly as it is at that moment, and git commit records only what is there. This lets you commit one change while others wait.
Branch
A name that points at one commit, and moves forward each time you commit on it. It lets you work on one thing without touching the main line. HEAD is git's marker for which branch you are on.
Main branch
The branch everyone treats as the real version of the project. Work happens elsewhere and joins it when it is ready. The name is only a convention: many older projects call it master.
Merge
Bringing one branch's work into another. If only one side has moved, git simply slides the branch forward. If both have, it finds the commit they share, combines the two sets of changes, and makes a new commit with two parents.
Merge conflict
What happens when two branches changed the same lines. Git can't choose, so it stops and writes both versions into the file between markers, and someone has to decide what the file should really say.
Rebase
Moving your commits so they start from a newer point, by replaying them one at a time. The result looks as if you began today and worked in a straight line. But each replayed commit is a new commit, with a new hash.
Remote
Another copy of the repository, usually on a server, which yours knows by name. The usual name is origin. Your machine also keeps its last-known note of where the server's branches were, called origin/main.
Push and pull
Push sends your commits to the remote. Pull fetches the remote's commits and brings them into your branch. Fetch only downloads, and changes none of your work. Nothing travels until you do one of these.
Pull request
A request, on a hosting site such as GitHub, to merge one branch into another. It shows the diff, collects comments and check results, and keeps the whole discussion attached to the change.
Clone and fork
A clone is a full copy of a repository on your machine, history included. A fork is your own copy on the hosting site, which you can change without asking anyone and later propose changes from.
.gitignore
A file listing the names and patterns git should not track, such as dependencies, build output and secrets. Git then behaves as if those files weren't there. It only applies to files git isn't already tracking.
Commit message
The note attached to a commit. Its first line says what changed, short enough to read in a list, and the body says why. Conventional Commits is a common format for that first line: fix(cart): stop charging VAT twice.
Small commit
A commit that does one thing and leaves the project working. If you need the word "and" to describe it, it is probably two commits. A rename, a bug fix and a reformat are three, even if they happened in the same hour.
Revert
Undoing a commit by adding a new commit that does the opposite. The mistake stays in the history along with its undoing, and nobody else's copy is disturbed.
Reset
Moving the current branch to a different commit. Soft leaves your files and staged work alone. Mixed, the default, also clears what is staged. Hard also overwrites your files to match that commit, which destroys uncommitted work.
Force push
Telling the server to replace a branch with yours, even when that throws away commits it has. A normal push can only add. This one can delete other people's work from the server, and it barely mentions it.
Stash
A shelf for unfinished work. git stash puts your changes to tracked files aside and returns your folder to the last commit, and git stash pop brings them back. New files git isn't tracking yet stay where they are unless you add -u.
Tag
A permanent name for one commit, usually a release such as v1.2.0. Unlike a branch, it doesn't move when you commit. An annotated tag also records who made it, when, and a message.
Blame
A view of a file showing, for each line, the last commit that changed it and who made it. The name is unfortunate: you use it to find out why a line exists, not whose fault it is.
Bisect
A way to find the commit that introduced a bug by halving the range. You name a good commit and a bad one, git checks out the middle, you say good or bad, and it halves again. A thousand commits takes about ten tests.
Worktree
A second working folder attached to the same repository, on its own branch. The folders share one history, but each has its own files, its own staged changes, and its own idea of which branch is current.
Git hook
A script git runs by itself at certain moments, such as just before a commit or a push. If the script exits with anything other than 0, git stops. Hooks live in your own copy of the repository and aren't part of its history.
GitHub
A website that hosts git repositories and adds what git lacks: pull requests, reviews, issues, permissions and automated checks on every push. Git is the tool. GitHub is one company's service built around it, and GitLab is another.
Reflog
Git's private diary of everywhere HEAD has been: each commit, checkout, reset and rebase. When a commit seems lost, it is usually listed here, and you can walk straight back to it.
Git guardrails
Rules at three levels that stop dangerous git commands: a deny rule in the agent's settings, a script that inspects each command before it runs, and protection on the server. Each one catches things the others miss.

4. Reading and debugging

Reading code
Working out what code does by following it. You rarely read a file from top to bottom. You start where the program starts, or where the problem showed up, then follow the calls, each place one piece of code starts another, and ignore everything that path never touches.
Variable
A name for a value the program is holding, like a label on a box. In JavaScript, let means the name can be given a new value later, and const means it can't.
Function
A named piece of code you run by writing its name followed by brackets. It lets one idea be written once and used in many places, and it lets a reader take in the name rather than the details.
Parameters and return values
Parameters are the inputs a function asks for, named in its brackets. The values you pass in are the arguments. return hands one value back to the caller and ends the function, and a function with no return hands back undefined, JavaScript's word for nothing.
Type
What kind of value something is: a number, some text (called a string), true or false (a boolean), and so on. The type decides what an operation means, so + adds two numbers but glues two strings together.
Conditions and loops
A condition (if) runs some code only when a test is true. A loop (for, while) repeats some code until its test turns false. Between them, they decide which lines run and how many times.
Lists and objects
A list, called an array, holds values in order, numbered from 0. An object holds values under names, like a small form. Both live in a box in memory, and a variable holds a pointer to the box, not what is in it.
Modules and imports
A module is a file that shares some of what it defines using export. Another file pulls those parts in using import. Anything not exported stays private, so a module's insides can change without breaking the files that use it.
Null and undefined
Two ways JavaScript says "nothing here". undefined usually means nothing was ever set, and null usually means someone set it to nothing on purpose. Reading a property of either one crashes the program, with an error you will see often.
Exception
An error that stops the current function and climbs back through whoever called it, until some code catches it using try and catch. If nothing does, the program ends.
Stack trace
What a crash leaves behind: the error message, then every function that was running at that moment, newest first, each with a file and a line. It is a map from where it blew up back to where it started.
Classes and objects
A class is a blueprint. Each object made from it with new gets its own data and shares the functions, called methods. Inside a method, the word this means the object it was called on.
Async and await
Slow work, such as a network call, doesn't hold everything up. The program gets a promise of a result and moves on. await pauses one function until its promise finishes, and other code gets to run in the meantime.
State
Everything a program remembers at a given moment: its variables, what is in its database, what you have selected. The same function can behave differently depending on state, so a bug can depend on what happened before, not only on what you did just now.
Side effect
Anything a function does beyond handing back its answer: writing to a database, sending an email, changing something outside itself, even printing. A program's useful work is mostly side effects, and so is most of its risk.
Pure function
A function whose answer depends only on its inputs, and which changes nothing else. Same input, same output, every time. Code that is not pure is called impure, which is no insult: impure code does the useful work.
Scope and closures
Scope is which names a line of code can see. A name made inside a function or a block can only be seen there. A closure is a function that keeps hold of the variables around where it was created, even after that code has finished.
Logging
Making the program write down what it is doing as it runs, with something like console.log. It lets you see inside a run without stopping it, and what comes back is evidence, not a theory about what happened.
Debugger
A tool that runs your program under your control. It pauses on a line you chose, shows you every variable and the call stack, and moves on one step at a time. Browsers have one built in, and so do most code editors.
Breakpoint
A mark on a line that tells the debugger to pause there, so the program can run at full speed up to the part you care about. A conditional breakpoint only pauses when a test you wrote is true.
Reproduction
A set of steps that makes the bug happen, ideally every time. Without one, you can't tell if a change fixed the bug or if it just didn't happen this time. A bug you can't reproduce isn't fixed, only quiet.
Minimal reproduction
The smallest input or program that still shows the bug. You get there by removing things until the failure goes away, then putting the last thing back. What remains is often close to an explanation.
Hypothesis
One specific guess about the cause that a single check could prove wrong, such as "the price is already a string by line 40". Debugging goes fastest when you test one at a time and change one thing at a time.
Debugging by halving
Finding a fault by checking the middle. If things are still right there, the bug is in the later half, and if not, the earlier half. Each check rules out half of what is left, so a thousand places takes about ten checks.
Explain it out loud
Explaining the problem line by line to anything at all: a colleague, a pet, a rubber duck. You often spot the mistake part way through, because explaining makes you say what you had only been assuming.
Root cause
The symptom is what you can see going wrong. The root cause is the earliest wrong thing that produced it, and the place where a fix ends it for good. A fix at the symptom only hides it, and it comes back somewhere else.
Off-by-one
Being wrong by exactly one at an edge: stopping a step too early or too late, or miscounting because lists number from 0. A list of 5 has positions 0 to 4, so position 5 is off the end.
Heisenbug
A bug that goes away or changes when you try to look at it, because looking changes the timing or the conditions. The name is a joke on Heisenberg's uncertainty principle.
Comments
Text in a file meant for people, which the program ignores. In JavaScript it starts with //. The useful ones say why the code is the way it is, which the code itself can't tell you.
Grep and code search
Searching every file for some text or a pattern. grep is the old command, and ripgrep (rg) a fast modern one. A regular expression is a small language for patterns: \bprice\b finds the word price, but not priced.
Language server
A program running beside your editor that understands your code's structure. It powers go to definition, find references, rename and the red underlines. Because it follows scope and imports, it knows which of five things called total you mean.
Fix loop
When an agent tries fix after fix for the same bug, each one plausible, none of them working, some undoing the last. More attempts rarely help when its idea of the problem is wrong. This is the point at which you step in.

5. The model

Language model
A program that takes text and outputs a probability for each piece of text that could come next. One piece gets picked and added to the text, and the step repeats. Everything it appears to do is built out of that step.
Token
The unit a model reads and writes: a chunk of text such as a short word, part of a long word, a space plus a word, or a single symbol. Limits are counted in tokens, and so is what you pay.
Tokeniser
The program that cuts text into tokens before the model sees it and joins tokens back into text afterwards. Its vocabulary is fixed in advance, so the same text can count differently on different models.
Training
Adjusting a model's numbers over a huge amount of text until it gets better at predicting what comes next. When training ends the numbers are frozen and shipped. Using the model doesn't change them.
Knowledge cutoff
The date after which a model's training text has little or nothing. Nothing tells it that time has passed, so it describes old versions and old APIs in the present tense unless the prompt says otherwise.
Inference
Running a trained model to get output. Each request is worked on separately, and the model itself carries nothing over from one to the next, so it starts every request knowing only what that request contains.
Context window
The most tokens one request can involve: instructions, the conversation so far, files read, and the reply. What is outside it can't affect the output, any more than a program can use a file it never opened.
System prompt
The part of a request set by whoever built the tool rather than typed by the user: the role, the rules, how to use tools. It is still text in the window, read as tokens like everything else.
Prompt
Everything sent to the model in one request: system prompt, tool definitions, earlier messages, file contents and your latest words. In everyday speech it means only what you just typed, which is usually a small part.
Sampling
Choosing the next token from the model's odds, by weighted dice. Temperature stretches or flattens the odds: low favours the likeliest token and high gives rare ones a chance. Top-p and top-k leave unlikely tokens out of the draw.
Non-determinism
The same input can give different output. Dice are the obvious cause. Even with the dice removed, a hosted model can vary, because of details such as how requests get batched together on the server.
Hallucination
Output that reads as fact and isn't: a package, function, flag or citation that doesn't exist. It is produced by the same step as correct output, so nothing in the text marks it, and confident wording tells you nothing.
Sycophancy
A tendency to produce what the person seems to want rather than what is true: backing down when challenged, praising weak work, confirming your guess about a bug.
Confabulated explanation
An account a model gives of its own behaviour, written as new text rather than read from a record. It may be right or wrong, and it reads the same either way. Asking "why did you do that" gets you a plausible story.
Tool call
Structured output asking for a named action with arguments, such as read_file on config.json. The model runs nothing. The program around it, which the next chapter calls the harness, decides whether to run it and sends back the result as text.
Thinking and effort
Tokens a model produces before its answer, working a problem through, which tends to help on hard tasks. Effort is the setting that controls how much of this happens. More effort costs more and takes longer.
Prompt caching
The provider keeps the processed start of your request for a few minutes. If your next request begins with exactly the same bytes, that part costs a fraction of the price. One changed byte invalidates everything after it.
Model tiers
Providers sell a ladder of models at very different prices. Higher rungs cost more per token, tend to be slower and tend to do better on hard work. The names change often, so check the current list rather than remembering one.
Token cost
What a request costs: the tokens of each kind multiplied by that kind's price per million. Input, cache writes, cache reads and output are all priced separately, and output is the most expensive, five times input on current Claude models.
Embedding
A list of numbers standing for a piece of text, produced so that texts with related meanings get similar numbers. Compare two lists and you get a measure of how related the texts are, even if they share no words.
Model benchmarks
A fixed set of tasks that models are scored on so they can be compared. SWE-bench is the best known for coding: given a real bug report from GitHub and the project's code, the model has to produce a change, and tests decide whether it worked.
Jagged frontier
Models do some tasks very well and others badly, and the boundary is not where you would guess: two tasks that seem equally hard can fall on opposite sides. The output looks equally polished on both.
Fine-tuning
Training a copy of a model further on your own examples, so that it leans towards your format or style. It changes tendencies. It isn't a way of giving a model your code base, which changes daily anyway.
Stop reason
A field on each response saying why the model stopped: it finished, hit your token limit, wants a tool run, or declined. It arrives on a success, so code that only reads the text can treat half an answer as a whole one.

6. The agent

Agent
A model, a loop and some tools. The model asks for a tool, a program runs it and hands back the result, and this repeats until the model says it has finished.
Agent loop
The cycle inside every agent: send the context to the model, read its reply, run any tools it asked for, add the results to the context, and send it all again. It ends when the model stops asking for tools.
Harness
Everything in an agent except the model: the loop, the tools, the instructions, the permissions, the hooks, the sandbox. It decides what the model sees and what happens to what it asks for.
Tool
A function the harness offers the model, described by a name, a purpose and the inputs it takes. The model can only write a request to use it. The harness checks the request, runs the function and returns the result.
Coding agent
An agent whose tools can read and edit files and run commands, so it can write code, run it, see what broke and try again. Claude Code, Codex and Cursor's agent are coding agents.
Vibe coding
Building with a model and not reading the code it writes. You accept every change, paste errors back in, and judge only by whether it seems to work. It describes how you work, not which tool you use, and it is fine for throwaway projects.
Agentic engineering
Building software with coding agents while staying answerable for the result. You set the goal, decide what the checks are, and can explain what shipped. The agent types, and you are still the engineer.
AGENTS.md and CLAUDE.md
A plain text file in your repo that the agent loads when it starts: build commands, a map of the code, things not to do. AGENTS.md is the name shared across tools. CLAUDE.md is Claude Code's own.
Rules file
Instructions that load only when they apply, usually when the agent touches certain files. A rule for database code stays out of the context until the agent opens database code.
Skill
A folder holding a SKILL.md file: a name, a one-line description and steps to follow, sometimes with scripts beside it. Only the name and description load at first. The agent reads the rest when the description matches what it is doing.
Slash command
A word starting with / that you type to make the harness do something right now: clear the context, switch mode, or run a saved prompt. You type it, not the agent.
Hook
A script the harness runs at a set moment, such as just before a tool runs or when the agent tries to stop. It can block the action. The model has no say in whether it runs.
Subagent
A second agent the main one starts for a side job. It gets its own context window and its own instructions, and hands back a summary. The thousands of lines it read never enter the main conversation.
MCP
Model Context Protocol: a standard way for an agent to use tools that live outside it. A server offers tools such as "search issues", and any agent that speaks the protocol can list and call them.
Code registry
A list of code you can pull into your repo as files you own, with a command that works out what else each piece needs. You end up with source in your tree that you can edit, and not a dependency someone else updates for you.
Permission modes
A setting for how much the agent may do before it has to stop and ask you. Modes run from asking about nearly everything to asking about almost nothing.
Allowlist
A list of actions the agent may take without asking. Anything not on it still stops for approval. Rules like Bash(bun test) are how you cut prompts without turning them off.
Sandbox
A boundary enforced by the operating system that limits what a running command can touch: which folders it can write to, which it can read, and where it can connect. It holds even when the agent has been tricked.
Plan mode
A mode where the agent can read and explore but can't edit your source files. It writes a plan, you read and change it, and only then does the work start.
Agent session
One run of an agent from its first message to its last, with its own growing context. When it ends, that context is gone unless you resume it, or the agent wrote something to a file.
Agent memory
Whatever carries over from one session to the next. There is nothing magic in it: it is files, put back into the context when a session starts. Some you write yourself. Some the tool writes for itself.
Headless mode
Running an agent with nobody at the keyboard: one command, one prompt, and output a script can read. It is how an agent runs on a schedule, or in continuous integration, the automatic checks on a server that chapter 9 covers.
Levels of autonomy
A scale for how much of the work an agent does before a person looks at it. At one end you approve every line. At the other you write a spec and judge only the result.
Human in the loop
A person has to approve at a chosen point before the work continues. That point could be each command, each plan or each merge.
Destructive actions
Anything that can't easily be undone: deleting data, force-pushing, dropping a table, sending an email, spending money. An ordinary mistake gets another attempt. These may not.
What the agent can reach
Everything the agent could touch if it wanted to, or if someone tricked it: your files, your environment variables, your logins, your network. That reach, and not the task you gave it, is the size of what could go wrong.

7. Context

Context engineering
Choosing what the model can see on each request: which instructions, files, tool results and history go in, and which stay out. The prompt is what you say. Context is everything else it reads before it answers.
Context budget
Treating the window as money you spend. Each token that goes in stays in, gets sent again on every later turn, and leaves less room for what comes next. Test logs and whole files are the big purchases.
The dumb zone
The informal claim that a model gets worse past some point in its window, so you should stay below it. That reliability falls as context grows has support. Any specific percentage is a working rule, because no one has shown us a measured line.
Instruction budget
The limit you set on instructions that always load. AGENTS.md goes into every request, so each line has to earn its place on every task, including the many it has nothing to do with. Short and specific beats long and thorough.
Progressive disclosure
Starting the agent with a small entry point and showing it where to look next: a short index now, details when they are needed. A skill's description is the index entry, and its body is the detail.
Just-in-time retrieval
Keeping lightweight pointers, such as file paths and search patterns, and loading what they point to only when it is needed. The agent searches, reads twenty lines and moves on, and never holds the whole repo in view.
Codebase map
A short description of how a repo is laid out: which folder does what, and where to begin. It gives the agent a picture of the project without reading it, so its first search is aimed at something.
Pointing at examples
Telling the agent to copy something that already exists: "follow the pattern in src/db/users.ts". One path, and the code does the explaining. It is about the cheapest useful context there is.
Retrieval (RAG)
Searching a body of text, taking the top matches and putting them in the prompt so the model answers from them. Keyword search (BM25 is the standard scoring formula) finds exact words. Embeddings find related meaning. Each misses what the other finds.
Context-efficient output
Making your tools print only what an agent can use: one tick when a check passes, and the full output only when it fails. The check still runs in full. Only the reading gets shorter.
Subagents as context hygiene
Sending noisy work, such as searching or reading big files, to a subagent, so the reading happens in its window and only a short summary comes back to yours. What you are buying is the clean window, not a specialist.
Context poisoning
A mistake that gets into the context and stays: a guess stated as fact, an invented function, a wrong summary. Every later turn reads it again and builds on it, so the agent's own earlier words keep arguing for the error.
Drift
A session slowly moving away from what you asked: the scope grows, an early rule stops being followed, the goal changes shape. No single turn looks wrong. You notice when the diff has things in it you never asked for.
Starting fresh
Ending the conversation and beginning a new one with empty context, then giving it only what it needs. Your files and commits stay. What it read and said is gone, unless it was written down.
Compaction
Replacing older turns with a summary, so a session can continue in less space. Most tools do it automatically near the limit, or when you ask. Whatever the summary leaves out is gone, and nothing flags the loss.
Handoff note
A short file one session writes for the next: what is done, what failed, what was ruled out, what to do next and how to check it. It is all that crosses from one empty context to the next, so it has to stand alone.
Research, plan, implement
Splitting work into three phases. Research how the code works now and write it down. Turn that into a plan file. Implement from the plan. Each phase starts from the last one's file with a small window, and you review the files.
Docs in the repo
Keeping decisions, plans and how-tos as plain files next to the code, not in a wiki or a chat. The agent can search them with the same tools it uses on code, they change in the same commit as the code, and review covers them.
The repo as the system of record
The rule that anything the work depends on lives in the repo, in a form the agent can read. A decision in a meeting, a chat thread or your head doesn't exist for the agent until someone writes it where the agent looks.
Agent legibility
How easily an agent can find out what it needs by itself: names it can search for, errors that say what went wrong, logs it can query, an app it can start. Whatever an agent can't observe, it can only guess about.

8. The brief

Brief
What you tell an agent before it starts: what to build, why, what counts as finished, and whatever it couldn't work out by itself. It can be one sentence or a page. Anything it leaves out, the agent decides for you.
Spec
A written description of what something must do, exact enough that two people, or two agents, would build the same behaviour from it. It says what and why, and usually leaves how to the builder.
Requirement
One thing the result must do, stated so that someone could check it. "apply ignores an event older than the newest one for that order" is a requirement. "Handle events properly" is a wish.
Acceptance criteria
The specific checks that decide whether this piece of work is finished, agreed before it starts. Each one passes or fails. The best are written so that a program can run them.
Definition of done
The list that must be true before anything counts as finished, on every task: say the code type-checks, the tests pass and the docs are updated. You write it once, and it applies to all the work.
Scope
The edges of the job: which files, features and behaviours this task may change, and which it may not. One line of scope can save a long review.
Non-goal
Something that could reasonably be a goal and that you have chosen not to pursue this time. "No offline mode in this version" is a non-goal. "It shouldn't crash" isn't, because nobody was ever going to want crashes.
Edge case
An input at the limit of what a program expects: nothing at all, exactly one, zero, the largest allowed, the same thing twice, things in the wrong order. Bugs gather here because the usual case is what everybody pictures.
Constraint
A limit on how the job may be done, rather than on what it must do: no new libraries, under 200 milliseconds, use the database we already have.
Examples
Showing what you want with concrete inputs and the results they must give, in place of or beside a description. A good one settles what a paragraph leaves open, and it is hard to read two ways.
Ambiguity
A sentence that can honestly be read more than one way. A model rarely stops to ask which you meant. It picks a reading and writes working code for it, so nothing looks wrong.
Have it interview you
Instead of writing the brief yourself, you ask the agent to question you until it could write it. It finds the decisions you hadn't noticed you were making.
Plan
The steps an agent intends to take, written before it takes them: which files, in what order, what it will check, and what it isn't sure about.
Plan as an artefact
A plan saved as a file in the repo, with steps that get ticked off, so that it survives the session. A later agent can pick it up, and a reviewer can see what was meant.
Spec-driven development
Working so that the spec comes first and stays the main thing: you write and review the spec, and agents produce the code from it. How far this goes varies, from a spec for one task to a spec that replaces code as what you edit.
The best spec is code
The opposite position: write code early, because code that runs answers questions a document can only guess at. A working version or a prototype becomes the description of what you want, and anything written comes after.
Vertical slice
A small piece of a feature that goes through every layer, from what the user sees down to where the data is kept, so it works end to end even though it does very little.
Decomposition
Splitting a big job into pieces small enough to be done and checked alone, in an order where each piece builds on something already known to work.
One task per session
Start a new session for each separate job, so one job's leftovers don't end up steering, or being paid for by, the next.
Spike
A small throwaway program written to answer one question, such as whether a library can do something or how a function really behaves. You keep the answer and delete the code.
Go deep first
Get one agent doing one hard thing well, with real understanding and real checks, before you run several at once. A setup you can't trust with one agent gives you ten times the mess with ten.
Prototype
A quick version built to help you decide something, such as which layout or how an interaction should feel. It is meant to be thrown away, and the real one gets built properly afterwards.
User story
One short sentence about who wants something and why, usually written "As a [someone], I want [something], so that [reason]." It starts a conversation and isn't meant to be the whole spec.
Stop condition
A rule the agent can check that says when to stop: these commands exit 0, or this many tries have been used. It stands in for the agent's own feeling that it has finished.
Ask, don't guess
A rule for the agent: when the answer changes what gets built and it can't find out for itself, stop and ask instead of quietly picking. People disagree about how often that should be.
The right word
Using the exact term of the trade instead of a description: "idempotent" for "handles repeats okay", "debounce" for "waits until I stop typing". One word can carry a set of requirements you would otherwise have to spell out, if you know it.

9. Backpressure

Harness engineering
When an agent makes a mistake, you don't just ask it to try again. You change its environment so that mistake can't easily happen again: a line in its instructions, a script it can run, a check it has to get past.
Backpressure
Any automated check that refuses an agent's work and tells it why, so that it corrects itself before a person is involved. Types, tests, linters and security scanners can all do this.
Guide
A control that acts before the agent does, steering it towards the right thing: an instructions file, a skill, a code template, an example to copy.
Sensor
A control that acts after the agent does, observing what it produced so it can correct itself: a test run, a type check, a screenshot, a review.
Computational control
A check run by ordinary code, so the same input should give the same answer, usually within seconds. Type checkers, linters and tests are computational.
Inferential control
A check where a model forms a judgement: an AI code review, a second agent grading the first. It can notice things no rule can express, such as whether a change makes sense.
Formatter
A program that rewrites your code into one fixed layout: spacing, line breaks, quote marks. It doesn't change what the code does, and running it a second time changes nothing.
Linter
A program that reads your code without running it and flags patterns you have decided are wrong. It takes milliseconds and never gets bored.
Errors as prompts
Writing an error message for the agent that will read it: what is wrong, where, and exactly what to do instead. The message goes straight into the agent's next turn, so it works as a prompt.
Type checker
A program that reads your code without running it and checks that each value is used as the kind of thing it is: no adding text to a number, no asking for a field that isn't there. For TypeScript that program is tsc, and tsc --noEmit only checks.
Strict mode
A setting that makes a type checker stop trusting you in the places it otherwise would. The one that matters most: with it off, a value that could be missing is treated as if it were always there, so the crash waits until the program runs.
Structural test
A test about how the code is arranged and not what it computes: which folder may use which, where the database may be touched. It reads the imports (the lines where one file pulls in another) and fails if a forbidden one appears.
Pre-commit hook
A script git runs when someone makes a commit. If it exits with anything but 0, the commit is refused. The git chapter showed how one works. The question here is what belongs in it: fast checks only, on what is really going in.
Stop hook
A script the harness runs when the agent tries to end its turn. If the script says no, the agent is told why and has to keep working.
Continuous integration
Everyone merges their work into the shared code often, and a server builds and tests each change on a clean copy of the project. That server is called CI too, and its green tick or red cross sits on the pull request.
Fast feedback
Run first the checks most likely to fail for each second they take, so a bad change hears no as early as possible. In practice that mostly means cheapest first: format, lint, types, unit tests, then the slow and costly ones.
Quality gate
A set of conditions work has to meet before it may go further, where failing any one stops it: types clean, tests pass, no new security findings. It answers yes or no, and nobody gets to argue with it on the day.
Check fatigue
What happens when a check says no to good work too often: nobody believes its no any more. Each wrong no is a false positive. So count how often a check's no turned out to be right, and keep it, fix it or demote it on that number.
Fail closed
When a check can't run or crashes, treat that as a failure and stop, rather than letting the work through. The opposite, fail open, lets the work through when the check breaks.
No bypass
The rule that nobody gets past a check by switching it off: skipping the hook, silencing the error, deleting the failing test. An agent may try any of these, so the rule has to be held by something that can see them, and not by asking.
Ratchet
A rule of thumb: when the agent makes a new kind of mistake, add something that catches that kind from then on. On an old codebase, record today's count of a problem and fail only when it goes up. Quality can then rise, and it can't quietly slip back.

10. Tests

Test
A small program that runs your code with a known input and checks the answer. If the answer is wrong it fails, loudly, without a person watching.
Assertion
The line in a test that compares what happened with what should have happened, such as expect(total).toBe(550). Without one, a test only proves the code did not crash.
Test runner
The program that finds your tests, runs them, prints what failed, and exits with a code saying whether everything passed. Examples are bun test, Vitest, pytest and Playwright Test.
Unit test
A test of one small piece of code on its own, usually a function. It runs in milliseconds and points straight at what broke.
Fixture
The known starting state a test sets up before it runs: a sample user, a few rows in a table, a file on disk. Good ones are created fresh for each test.
Test double
Anything that replaces a real part of your system during a test, like a stunt double. It lets you test without charging a real card or waiting on a real server.
Mock
A test double that records how it was called, so the test can check the calls. In casual use, people say mock for any stand-in.
Integration test
A test where several real pieces work together: your code against a real database, or two of your services talking to each other. It is slower, and it finds the bugs that live in the joins.
Contract test
A check that a real outside service still behaves the way your test doubles say it does. If the provider renames a field, this fails, even while everything else stays green.
End-to-end test
A test that drives the whole system the way a user would: a real browser, clicking real buttons, against the real app and its database.
Acceptance test
A test written from what the customer asked for and not from how the code works. Often written in Given, When, Then sentences that a person can read and a tool can run.
Smoke test
A very quick check that the thing runs at all: it starts, the main page loads, the health endpoint answers. It says nothing about whether it is right, only whether it is on fire.
Test pyramid
A rule of thumb for the mix: many fast unit tests at the bottom, fewer integration tests in the middle, and very few slow end-to-end tests on top.
Flaky test
A test that sometimes passes and sometimes fails on the same code. Usually the cause is timing, shared state or something outside the test, such as the network or the clock.
Regression test
A test written after a bug, which fails on the old code and passes on the fix. A regression is when something that used to work stops working.
Snapshot test
A test that saves the output once to a file, then fails whenever later output differs. It tells you something changed. It can't tell you whether the change is good.
Characterisation test
A test that records what old code does today, bugs included, so you can change it safely. You are writing down the behaviour before you touch it, without claiming that it is right.
Test-driven development
Writing the test before the code that makes it pass, in very small steps. The test fails first, because the code does not exist yet, and that failure is the point.
Red, green, refactor
The TDD cycle in three steps. Red: write a test and watch it fail. Green: write just enough code to pass. Refactor: tidy up while the tests stay green.
Test oracle
Whatever tells you what the right answer is. It may be a number you worked out by hand, a spec, an old system, or a rule that must always hold.
Coverage
The share of your code that ran during the tests. It says what ran. It says nothing about whether anything checked the result.
Tautological test
A test that can't fail, because it compares the code with itself, checks nothing, or only checks something that is always true.
Goodhart's law
When a measure becomes a target, it stops being a good measure. Point anyone at a number and they will move the number, whether or not the thing it stood for moves too.
Mutation testing
A tool makes one small deliberate bug in your code, such as changing a < to <=, and runs your tests. If they fail, that bug was caught. If they still pass, your tests have a blind spot exactly there.
Mutation score
The share of deliberate bugs your tests caught: killed divided by total. 18 of 30 is 60%. It measures how strong the tests are, not how right the code is.
Equivalent mutant
A mutant that changes the code but not what it does, so no test could ever catch it. It survives, and that says nothing bad about your tests.
Property-based testing
Instead of a few examples, you state a rule that must always hold, such as "the shares always add up to the bill". The tool invents hundreds of inputs, and when one fails it cuts it down to the smallest input that still fails.
Fuzzing
Throwing huge numbers of random or damaged inputs at a program to see if it crashes or hangs. You do not need to know the right answer, only that it should survive.
Empirical verification
Checking a claim by running the real program on the surface a user touches and looking at what happens: open the page, send the request, read the row in the database. What you saw counts, and what the agent says it saw does not.
Invariant
Something that must always be true, at every moment, whatever happens: a balance never goes below zero, a refunded order never ships, the shares always add up to the bill. It is a plain sentence first and code second.
Model checking
A tool walks every state a small model of your system can reach, in every order the steps could happen, and checks an invariant in each. If one breaks, it hands you the shortest sequence of steps that gets there. The model is a short description of the design, not your code.
Formal verification
Proving that code or a design meets a written specification for all inputs, not only the ones you tried, with a machine checking the proof. It covers what the spec says, under what the proof assumes, and nothing else.
Statechart
A drawing of a system as the states it can be in and the moves between them. Anything not drawn isn't allowed, so a refunded order simply has no arrow to shipped. A statechart adds states inside states, and regions that run side by side.
Test tampering
Changing the tests so they pass, in place of fixing the code: skipping a test, deleting it, changing the expected answer, weakening the check, or making the code recognise the test's exact input.
Holdout scenario
A test of what the software should do, kept where the agent can't read it or change it. The agent is judged on it afterwards, so it can't fit its work to it.
Verification spend
Choosing where a limited budget of tokens and attention goes: mechanical gates, running the real thing, formal checks, or a model reading the code. Each sees things the others can't, so ask what this change could get wrong, and which check could see that.
Eval
A test for an AI system: give it a task, grade the result, and do that many times, because it may answer differently each time. The result is a rate, not a pass or a fail.

11. Design

Good code
Code that is cheap to change correctly. Two programs can pass the same tests today and differ hugely in what next week's request costs. Working is the minimum, and how easily it changes is what separates them.
Naming
Choosing what to call things so a reader can guess what they do without opening them. unpaidInvoices tells you something. data tells you almost nothing.
Small functions
The advice that functions should be short, so each does one thing and has a name that says what. How short is where people stop agreeing. One famous book says very short. Another says too short makes code harder to read.
Cohesion
How much the things inside one module belong together. High cohesion means that when one part changes, the rest tend to change with it, and nothing unrelated gets dragged along.
Coupling
How much one module has to know about another. If changing A forces you to change B, they are coupled. Modules have to talk to each other, so you can't get rid of it. The questions are how much, and whether you can see it.
Separation of concerns
Keeping different kinds of decision in different places: what the tax rule is, how it is stored, how it is shown. Then you can think about one, and change one, without reading the others.
Abstraction
A simpler way to think about something complicated, leaving out what you don't need right now. save(user) lets you forget about disks and SQL. Every well-named function is a small abstraction.
Leaky abstraction
An abstraction whose hidden detail shows through anyway, usually at the worst moment. The interface promises something simple, and what sits underneath forces you to care about it after all.
Interface
Everything one module must know to use another: function names, what they take, what they return, what can go wrong, and any rule that isn't written down anywhere.
Deep module
A module that does a lot behind a small interface. A shallow one has an interface nearly as complicated as what it does, so using it spares you very little. The words are John Ousterhout's.
Single responsibility
The rule that a module should have one reason to change. "Reason" is the word people miss: Robert Martin means one group of people whose requests cause the change, which isn't the same as doing one task.
SOLID
Five design rules for code built from classes, under one acronym: Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion. They give you words for arguing about design.
DRY
Don't repeat yourself: each piece of knowledge should live in one place, so changing it means changing it once. It is about knowledge and not about text. Two lines can look alike and mean different things.
Rule of three
Put up with the first duplicate. When you are about to write the same thing a third time, extract it. By then you have enough examples to see what is really shared.
YAGNI
You aren't gonna need it: don't build something now because you guess you'll want it later. Build it when you do want it.
KISS
Keep it simple, stupid. Prefer the plainest design that does the job, because someone will have to fix it under pressure one day, without its author there to explain it.
Dependency injection
Passing a function the things it needs, so it doesn't have to go and get them. isExpired(token, now) can be tested at any date. A function that reads the real clock inside can only be tested today.
Composition over inheritance
Build behaviour by combining small parts, rather than stacking parent and child classes. Want a client that logs and retries? Wrap the client in something that adds each behaviour, rather than extending it.
Layered architecture
Dividing a program into layers, such as interface, rules and storage, where each layer may only use the ones beneath it. The rule about direction is what does the work.
Clean architecture
Robert Martin's version of layering: business rules sit at the centre and know nothing about databases or web frameworks. Those sit on the outside and depend inwards, so they can be replaced.
Boundary
A line in the code where one part hands over to another: your code and the network, one module and the next, your code and a library. What crosses it should be checked and kept narrow.
Parse, don't validate
Where data enters, turn it into a type that can only hold good data, rather than checking it and passing the original along. After that nothing needs to check again, and nothing can forget to.
Make illegal states unrepresentable
Design your data so that a wrong combination can't even be written down. An order that is both cancelled and shipped should be impossible to express, rather than something every function must remember to check.
Refactoring
Changing how code is organised without changing what it does, in small steps, running the tests after each one. If the behaviour changed, it wasn't refactoring.
Code smell
A pattern in code that suggests a problem without proving one: a very long parameter list, one module reaching into another's data, the same switch in five places. It is a prompt to look, and it isn't a verdict.
Technical debt
A metaphor: taking a shortcut now is like borrowing. You get the feature sooner, and then you pay interest on every later change until you pay it back.
Cyclomatic complexity
A count of the separate paths through a function: one, plus one for each fork, such as if, a loop, a case or &&. More paths mean more to understand and more tests to cover them.
CRAP score
One number combining how complicated a function is with how little of it the tests run. Complicated and untested scores terribly. Simple or well tested scores low. The formula is complexity squared, times untested fraction cubed, plus complexity.
Duplication detection
A tool that finds code repeated across a project, usually ignoring names so that a renamed copy still counts. It hands you candidates, and you decide whether they are really the same idea.
Slop
Agent output that works and that nobody would have chosen to keep: checks for cases that can't happen, comments that restate the code, helpers with one caller. The tests pass, which is how it gets in.
Agent sprawl
An agent building more than you asked for: extra files, options and layers for a small job. Each addition is reasonable on its own, and the total is a bigger thing to carry for as long as the code lives.
Monolith and microservices
A monolith is one program, deployed as one thing. Microservices split it into many small programs that talk over a network, each deployed by itself. One is simpler to run. The other lets teams move separately.
Architecture decision record
A short text file in the repo recording one design decision: the situation, what was decided, and what it will cost. You don't rewrite it later. A new record replaces the old one.
Simple versus easy
Easy means close at hand or familiar. Simple means not tangled together. The two are independent: a tool can be easy to start with and leave you a knot. Rich Hickey drew this line in a 2011 talk.

12. Review

Green doesn't mean right
A passing check only proves what it checked. When one agent writes the code and its tests, all of them can pass while the code does the wrong thing, because the tests came from the same misunderstanding.
Code review
Someone other than the author reads a change before it joins the main branch and decides whether it should. It is a judgement about the change, made by a person or an agent, on top of whatever the automatic checks said.
Reading a diff
A diff shows a change rather than a program: red lines went away, green lines arrived, and plain lines are context. You read it for what changed, and for what should have changed and did not.
What to look for, in order
A review has an order: is this the right change, is it designed sensibly, does it work, is it tested, can it be read. Style comes last, because a linter should be handling it.
Blast radius
How far a change can reach: everything that imports it, calls it or relies on how it behaves, directly or through something else. A one-line change to shared code can have a bigger blast radius than a thousand new lines nobody uses yet.
Self-evaluation bias
An agent marking its own work gives itself too high a mark. It checks what it meant to build rather than what it built, and from the inside those look the same.
A fresh agent
A new session with none of the conversation that produced the code, handed the diff and the spec and asked to judge it. It has no history to defend and no memory of why any of this seemed like a good idea.
The reviewer's prompt
The words you give an AI reviewer. They set how hard it pushes, and they can move the verdict more than the code does. So the prompt is a setting with a cost on each side, and you choose it knowingly.
Findings must show evidence
A review finding has to come with what proves it: the line, the input, what happens and what should happen. A finding without that is an opinion, which is worth having, and which should not stop a merge.
Review in the abstract
Reading code with nothing to check it against: no run, no stated intent, no question to answer. The reviewer fills the gap with what can be said about any code, which means small style points and warnings about things you may not need.
AI code reviewers
A product that reads your pull requests with a model and leaves comments on the lines it doubts. Most of them comment and leave the decision with a person.
You own what you merge
Whoever merges a change answers for it, whoever or whatever typed it. That means being able to say what it does, what could go wrong, how you would notice, and how you would undo it.
Code owners
A file in the repo that maps paths to the people or teams responsible for them, so a pull request touching those paths automatically asks the right reviewer. On GitHub it can also be made a requirement for merging.
Comprehension debt
The gap between how much code exists and how much of it anyone understands. Like money borrowed, it costs nothing today, and you pay later, in the time it takes to work out the code before you can safely change it.
Cognitive debt
A close cousin of comprehension debt, and many writers use the two as one. Where a difference is drawn, this one is about people rather than code: a team gradually losing its shared picture of how the system works and why.
Explain it back
Before accepting code, say what it does in your own words, including what it does on awkward inputs, then check yourself by running it. If reality disagrees with you, you have just found what you did not understand.
The review bottleneck
The point where agent-written work piles up waiting for someone to read it. Writing code got cheaper and reading didn't, so the queue in front of reviewers is now what limits how fast a team ships.
Small pull requests
Keeping each pull request to one reviewable idea, often a few hundred lines at most. Long changes get split so that each piece makes sense and passes its checks by itself.
Stacked diffs
A long change split into a chain of pull requests, each built on the one before it, so each can be reviewed alone and you don't have to wait for the first to merge before writing the next.
Making work reviewable
Doing the work so a reviewer can check it cheaply: one idea per pull request, a description saying what changed and why, and pasted evidence that it works, with the output of what you ran. You spend your time to save theirs.
Nit
A review comment marked as small and optional: a matter of polish that the author can take or leave. The label tells them not to hold the change up for it.
Blocking and non-blocking
A blocking comment must be dealt with before the change can merge. A non-blocking one is advice. Saying which one you mean is half of what makes a review useful.
LGTM
Short for "looks good to me": the usual way to approve a pull request. It is supposed to be a claim that you read it and would stand behind it.
Rubber-stamping
Approving without really reviewing, because the last fifty were fine and there are ten more waiting. The approval still gets recorded, so from outside it looks exactly like a review.

13. Security

Threat model
A short written answer to: what are we building, what can go wrong, what will we do about each thing, and did that work? It turns "be secure" into a list you can check.
Attack surface
Every place someone outside can send your system something: forms, URLs, uploads, webhooks, headers, and any file or page your agent reads. The bigger it is, the more you have to defend.
OWASP Top 10
A list of the ten most serious kinds of web application risk, kept by the non-profit OWASP and updated every few years. The trade uses it as shared vocabulary, and it is a good first checklist for a review.
Injection
Text from a user gets pasted into something another program reads as instructions: a database query, a shell command, a web page. The program can't tell which part you wrote, so the user's text can become commands.
SQL injection
SQL is the language for asking a database for things, as in SELECT * FROM users WHERE name = 'alice'. Paste a user's text into that sentence and they can rewrite the question. A parameterised query sends the value separately, so it can only ever be a value.
Cross-site scripting
An attacker gets their text into your page, and the visitor's browser runs it as code. That code runs as your site, with the visitor's logged-in session, so it can do whatever they can.
Output encoding
Converting a value when you put it into a page, so the browser reads it as text. The right conversion depends on where it lands: inside a tag, in an attribute, or in a link are three different problems.
CSRF
Another website makes your visitor's browser send a request to your site. The browser attaches their cookie automatically, so your server sees a logged-in user asking to do something they never asked for.
SSRF
A feature fetches a URL the user gave it, such as an image from a link. The attacker gives it an internal address, and your server, which sits inside your network, fetches what the attacker could never reach.
Path traversal
A filename from a user includes ../, which means "the folder above", until it climbs out of the folder you meant to serve. Then your server hands over files you never meant to expose.
Open redirect
A link on your own site sends visitors wherever a parameter says, as in /login?next=... An attacker sends a link that starts with your trusted address and ends on theirs, ready for a convincing fake page.
Input validation
Checking that what arrives is what you expect, in type, length and format, and refusing it if not. It must run on the server, because anyone can skip the browser and send the request directly.
Memory safety
Code is memory-safe when it can't read or write memory it doesn't own. C and C++ leave that to the programmer, so one wrong length can overwrite whatever sits next to it. Languages like Rust, Go, Java and Python check it for you, or won't let you write it.
Authentication
Proving who someone is: a password, a code from their phone, a passkey. The result is usually a session, so the server recognises them on every later request.
Authorisation
Deciding what a known user may do, on this thing, right now. The server has to decide on every request, because anything in the browser can be changed by the person using it.
Broken access control
The server fails to enforce what a user may do, so they can do it anyway: open an admin page, change a role, act on data that isn't theirs. It tops the OWASP list.
IDOR
The kind of broken access control you can do with a keyboard. /invoices/1003 is yours, so you try /invoices/1004 and get a stranger's, because the server looks up the id and never asks whose it is.
Password hashing
Storing a scrambled form of a password that can't be turned back. At login you scramble what they typed and compare. It has to be deliberately slow, and salted with a random value for each user.
Encryption in transit and at rest
Scrambling data so only someone with the key can read it. In transit protects it on the wire, and that is what HTTPS does. At rest protects it on disk. Each covers one place, and neither stops a request your app treats as valid.
JWT
A login token the server signs and the browser sends back. It has three parts: header, payload, signature. The payload is only encoded, so anyone can read it. The signature proves it hasn't been changed, if the server checks it properly.
Secret
A value that grants access: a password, an API key, a signing key. It belongs outside the code, in an environment variable or a secret manager, and it should only ever be readable by what needs it.
Secret scanning
A tool that searches your code and history for things that look like keys. It looks for known shapes, like an AWS key, and for strings that look too random to be ordinary text. That second measure is called entropy.
Least privilege
Giving each person, program and agent only the access its job needs, and no more. Then when one of them is fooled or compromised, the damage stops at what it could reach.
CORS
A browser rule: a script on one site can't read a response from another site, unless that site's server says it may. The server says so in a header, Access-Control-Allow-Origin. It only constrains browsers, so curl ignores it.
Content Security Policy
A header that tells the browser what this page may load and run: scripts only from here, no plug-ins, no framing. If an attacker's script gets into the page anyway, the browser can refuse to run it.
Security headers
Lines your server adds to each response that turn on browser protections: always use HTTPS, don't guess file types, don't let other sites frame this page, don't leak the full address when linking out. They take minutes to add.
Rate limiting
Capping how many requests one person or address can make in a period, and answering 429 Too Many Requests after that. It makes guessing a password or a code slow enough to be pointless.
Supply chain attack
Attacking you through something you depend on. A package gets taken over or swapped, you install the update as usual, and its code runs with all the access your program or your laptop has.
Slopsquatting
A model invents a package name that sounds right. It fails to install, and that's a clue. Then somebody notices the invented name and registers it with their own code, and now the same mistake installs without a murmur.
Dependency audit
Checking the versions you have installed against a public list of known vulnerabilities. npm audit is one such command. It can only find what has already been reported.
CVE
A public id for one known security flaw, such as CVE-2025-54136, so everyone can talk about the same bug. Its severity is usually given as a CVSS score from 0 to 10.
SAST and DAST
Two kinds of automated security check. SAST reads your code without running it. DAST runs your app and attacks it from the outside. Each finds things the other can't.
Prompt injection
Text gives a model orders it wasn't meant to take. A model reads your instructions and a web page as one stream of words, so a line in that page can say what to do next. Indirect means it was planted somewhere the agent would read.
Lethal trifecta
Simon Willison's name for three powers that are dangerous together: access to your private data, exposure to untrusted content, and a way to send data out. With all three, a stranger's text can steal your data. Remove any one and that attack has no route.
Tool poisoning
An MCP tool's description is read by the model, and you usually see a short version. A malicious server hides instructions in it, such as read this file and pass it along. The tool can also change after you approved it, which is called a rug pull.
OWASP Top 10 for LLM apps
A separate OWASP list for apps built on language models. Prompt injection is first. It also covers leaks of private data, poisoned models, trusting model output too readily, and giving a model too much power.
Sandboxing an agent
Having the operating system fence in an agent's commands: which files they can touch and which other machines they can reach. It holds even if the agent is fooled, because it's enforced from outside the model.
How often AI code is insecure
Studies ask models to write code for risky tasks and scan the result. Numbers near half failing get quoted widely. They come from particular tests with particular limits, so they're a warning that this happens, not a rate for your codebase.
Security review
Reading a change only for how it could be abused, separately from whether it works. It asks: who can reach this, what can they send, and what's the worst they can do? A person or a fresh agent can do it.

14. Data and failure

Database
A program whose job is to keep data safe and find it again quickly, while many other programs read and change it at once. Your app asks it questions over a connection. If your app crashes, or the database itself does, what it said it saved is still there.
Table and row
A table is a named collection of records that all have the same fields, like a strict spreadsheet. A row is one record, such as one order. A column is one field, such as its total, and every value in it is the same kind of thing.
Schema
The declared shape of your data: which tables exist, which columns they have, what type each holds, and the rules each must obey, such as not empty, or never below zero. The database enforces those rules on every write, whoever is writing.
Primary key
The column that identifies one row and only one, for ever. It must be present and it must be unique. Usually it's a number or a random id with no meaning, because anything with meaning, like an email address, can change.
Foreign key
A column in one table that must match the primary key of a row in another. An order's customer_id has to point at a real customer. The database refuses anything that would leave it pointing at nothing, and you choose what happens when the row it points at is deleted.
Unique constraint
A rule that no two rows may have the same value in a column, or in a set of columns. The database checks it as each row goes in, so it holds even when two people try in the same millisecond. The loser gets an error.
SQL
The language for asking a relational database for things. You describe what you want, such as which rows, in what order and how many, and the database works out how to get it. SELECT reads. INSERT, UPDATE and DELETE change. It looks like English, and small mistakes in it can be enormous.
Query plan
The steps the database chose to answer your query: which table to read first, whether to read all of it or use a shortcut, and how to join. You write what you want, and a part of the database called the planner decides how. EXPLAIN shows you its decision.
Index
A separate sorted structure that lets the database find rows without reading the whole table, like the index at the back of a book. The usual kind is a B-tree, a wide shallow tree you can walk from top to bottom in a few steps, however many rows there are.
N+1 query
One query to fetch a list, then one more for each item in it. A page of 50 orders that looks up each order's customer separately makes 51 trips to the database. Each is fast, and the page is slow. One query can usually fetch them all.
ORM
A library that lets you work with database rows as objects in your language, and writes the SQL for you. Prisma, Drizzle, Django and Active Record have one. It's convenient, and it hides how many queries a single innocent line of code will run.
Transaction
A group of database changes that succeed or fail as one. You BEGIN, make the changes, then COMMIT. If anything fails before the COMMIT, or the power goes, none of them happened. Moving money is the classic case: the debit and the credit must both happen, or neither.
ACID
Four promises a transaction makes. Atomic: all of it or none. Consistent: your rules still hold afterwards. Isolated: others don't see it half-done. Durable: once it's committed it stays, through a crash. It's a word you'll hear in interviews, and each letter is something you can break.
Isolation level
How much one transaction can see of others running at the same moment. Stronger levels hide more, and may refuse a transaction and make it retry. Weaker levels let strange things through. Dirty read, non-repeatable read and lost update are the names of those strange things.
Race condition
A bug where the result depends on who gets there first. Two people buy the last ticket: both read one left, both subtract one, both write zero. Two sales, one ticket. Each step was right, and the bug was the order they ran in.
Locks and atomic updates
Three ways out of a race. An atomic update does the maths inside one statement: SET stock = stock - 1. A lock makes others wait: SELECT ... FOR UPDATE. A version check lets everyone try and makes the loser start again. Try them in that order.
Deadlock
Two transactions each hold something the other wants, so neither can move. One locked row A and wants B, and the other locked B and wants A. They would wait for ever, so the database notices the cycle, kills one of them, and that one has to try again.
Migration
A script that changes the structure of a live database, such as adding a column, and is kept in your repo so that every copy can run it in order. The hard part is that, for a while, old code and new code are running against it at once.
Expand and contract
Making a breaking change in safe steps. Add the new thing alongside the old, have the code write to both, copy the old data over, move reads across, stop using the old, and only then remove it. At each step the old and the new code both work.
Backup and restore
A backup is a copy of your data, kept somewhere a mistake can't reach it. A restore is getting it back. Until you have really done a restore, you don't know the backup works, and a replica doesn't count, because it copies your mistakes too.
Partial failure
When some of the work happened and some didn't, and you may not be able to tell which. On one machine, a thing either ran or it crashed. Across a network, you sent a request and heard nothing: it might have failed, or it might have worked and the reply got lost.
Idempotency
An operation is idempotent if doing it twice has the same effect as doing it once. A client makes that true of a payment by sending a unique key with the request. The server saves the first result against that key, and a repeat gets that result back and charges nothing.
Retry and backoff
Trying a failed call again, and waiting longer each time. Backoff is the growing wait. Jitter is making each wait random, so that clients which failed together don't all come back together. Without those, retries can keep a struggling server down.
Delivery guarantees
What a message system promises. At most once: it may be lost, and it never repeats. At least once: it won't be lost, and it may arrive twice. Most systems you use give you at least once, so your code has to cope with seeing the same thing again.
Out-of-order delivery
Messages can arrive in a different order from the one they were sent in, because a retry of an old one can land after a newer one. If your code treats the latest to arrive as the latest to happen, a late "paid" event can undo a refund.
Timeouts and deadlines
A timeout limits one call. A deadline limits the whole job: the moment by which the answer stops being any use, handed down through every call that serves it, so nobody keeps working for a user who has gone.
Circuit breaker
A switch around a call to something that might fail. Count the failures, and past a limit stop calling it for a while and fail at once. After that, let one trial call through. If it works, close again. Named after the thing in your fuse box.
Queue
A list of jobs waiting to be done, usually run by a separate service. One program adds a message, and a worker takes it later and deletes it when it's finished. The caller doesn't wait, and a spike of work waits in the queue and not on your server.
Graceful degradation
Doing less when part of the system is unwell, in place of falling over. Hide the recommendations, serve a slightly old list, turn off the search, and keep the page up. You decide in advance what the product can live without, and what it can't.
Money and floats
Computers store most decimals in binary, which can't hold 0.1 exactly, so sums drift. A float is fine for measuring distance, and wrong for money. Store money as a whole number of the smallest unit, such as pence, or use a decimal type, and decide where rounding happens.
Dates and time zones
An instant is one point in time, everywhere. What a clock on the wall shows depends on where it is and on that place's current rules. Store instants in UTC and convert when you display. A time in the future, like a meeting, is different: store the wall-clock time and the place.
Replication
Keeping copies of a database on other machines. One copy, the leader, takes the writes and sends them to the followers, which can serve reads. Usually it sends them after telling the client yes, so a follower is a little behind. That gap is called replica lag.
Eventual consistency
A promise that all copies will agree if you stop changing things and wait. Until then, different readers can see different answers. It's a fair trade for speed and uptime, as long as the product was designed for it and it isn't a surprise.
CAP theorem
When a network splits your copies of the data apart, you have to choose. Either refuse some requests, so nobody gets a wrong answer, or answer them all, and accept that some answers are out of date. You can't have both while the split lasts.
Personal data
Anything that can be tied to a real person: a name, an email address, a location, an account number. It carries legal duties in much of the world. It gets everywhere, into logs, backups, test databases and, now, an agent's context, which may leave your machine.
Agents and production data
An agent with production credentials can delete data as fast as it can type. So keep credentials it can read away from production, give it a read-only role when it needs to look, and put destructive steps behind something it can't talk its way past. A sentence in its instructions doesn't count.

15. Performance and cost

Measure first
Before changing anything to make it faster, time it, find the slow part and write the number down. Then time it the same way after the change. Without both numbers, nobody can say the change helped.
Latency and throughput
Latency is how long one thing takes. Throughput is how many things get done per second. They are separate numbers, and improving one can hurt the other: waiting to send items in a batch gets more done per second, and makes each item wait longer.
Percentiles
Sort every timing from fastest to slowest. The 95th percentile, or p95, is the value that 95% of them are at or under. p50 is the middle one. A percentile is a time someone really waited, which an average need not be.
Tail latency
The slowest few requests, far along the end of the distribution. One in a hundred sounds rare until a single page makes dozens of requests and waits for them all, at which point a lot of people meet that one.
Benchmark
A repeatable test that times a piece of code many times under the same conditions, so two versions can be compared. One timing isn't a benchmark, because the same code gives a different number on each run.
Profiler
A tool that watches a program run and reports how much time each function took. Self time is what the function spent on its own. Total time also includes everything it called. The answer often surprises people.
Flame graph
A picture of a profile. Each bar is a function, sitting on top of the one that called it, and the wider the bar, the more time it took. You look for the wide bars at the top: they are doing the work themselves, with nothing above them to blame.
Big O
A way of saying how a program's work grows as its input grows. With O(n), twice the data takes about twice as long. With O(n²), twice the data takes about four times as long. It says nothing about how long any one run takes.
Bottleneck
The one stage that limits how much the whole line can do. Speeding up any other stage changes nothing at the end, and just makes a bigger pile in front of the narrow part.
Amdahl's law
If part of a job has to be done one step at a time, adding more workers can only speed up the rest. If 5% must run alone, you can never go more than 20 times faster, however many workers you add.
Premature optimisation
Making code faster, and usually harder to read, before you know that it matters. The cost is real and paid at once in complexity. The gain is a guess until someone has measured that this code is where the time goes.
Caching
Keeping a copy of an answer somewhere quick, so you can skip the slow work next time. A hit is when the copy is there. A miss means doing the work anyway. A cache is small, so something has to decide what to throw out, often the least recently used.
Cache invalidation
Getting rid of a stored copy when the real answer changes. Do it too late and people read old data, which is called a stale read. A time limit on each copy, or TTL, is the blunt way: it is simple, and wrong until it runs out.
Queueing and utilisation
When work arrives at random, it sometimes bunches up and has to wait in line. Utilisation is how busy the server is. As it nears 100%, the line grows faster and faster: at 50% a request takes about twice its work time, at 90% ten times, at 99% a hundred times.
Load test
Sending a system a realistic amount of made-up traffic, on purpose, to see how it behaves before real people do. A stress test goes past the expected load, to find where it breaks.
Concurrency and parallelism
Concurrency means juggling many tasks, swapping between them while each waits for something. Parallelism means truly doing several at the same instant, on separate cores, the independent workers inside a CPU. Waiting can be juggled. Crunching numbers needs more cores.
Event loop
In a browser or Node, a single line of work, called a thread, takes jobs off a list and finishes each before starting the next. While a job runs, nothing else can: no clicks, no animation, no other requests. A job over 50 ms in a browser is called a long task.
Connection pool
A fixed set of open database connections that requests borrow and hand back. Opening a new one each time is slow, so they are reused. If all are in use, a request waits. If code forgets to hand one back, the pool slowly runs out.
Memory leak
Memory the program no longer needs, and can't release because something still points at it: a list that only grows, a listener never removed. Each bit is small, so it passes every test and takes days to bring a server down.
Garbage collection
The part of a runtime that finds memory nothing can reach any more and frees it, so you don't have to. It costs work, and some of that work can pause your program. Those pauses are one reason a fast function sometimes isn't.
Core Web Vitals
Three scores for how a page feels. LCP: how soon the main content appears. INP: how soon the page responds when you tap. CLS: how much things jump around. Good means LCP within 2.5 seconds, INP within 200 ms and CLS at 0.1 or less.
Bundle size
How much code a page makes the browser download. A browser then has to unpack it, read it and run it, so on a cheap phone a big bundle costs time long after the download has finished.
Lazy loading
Not loading something until it is needed: an image as it nears the screen, a chart's code when someone opens the chart. The first view gets lighter, and anyone who never scrolls that far never pays for it.
Image optimisation
Sending an image no bigger than it will be shown, in a format that compresses well, with its size stated in the page. Images are often the largest thing a page downloads, so this can be the cheapest big win going.
Performance budget
A limit you set in advance on something like bundle size or p95 latency, with a check that fails when it is broken. Speed then stops being something you remember to care about, and becomes something that says no.
Cost per task
What it really costs to get one piece of work finished: every try, every check and the failures you paid for and threw away. The price per token is only a price list. This is the number you can compare.
Spending tokens well
Deciding what is worth putting in front of the model. Every turn sends the whole conversation again, so a big log read early isn't paid for once. You pay for it again on each turn until the session ends.
Model routing
Sending each job to a model that fits it, instead of one model for everything: a cheap one for searching and summaries, an expensive one for planning and hard bugs. The router can be a rule, a setting or a person.
Cache hit rate
The share of a request's input tokens that came from the prompt cache. Because an agent resends everything each turn, a high rate can cut the input bill several times over, and a low one can quietly cost more than having no cache at all.
Cost of an agent bill
Working out the whole bill from its parts: people, tasks per day, cost per task. Once you have those three, you can tell what would double it, what a cut would save, and whether the work was worth what it cost.

16. Shipping and running

Production
Where your software runs for real, with real users, real data and real money. Every other copy of it exists to prepare for this one.
Environment
One complete place your software can run, with its own address, its own data and its own settings. Development on your machine, staging and production are the usual three.
Staging
An environment that copies production as closely as you can afford, where a release runs before real users get it.
Build
The step that turns source code into the thing that actually runs: compiling, bundling, and copying everything into one output.
Semantic versioning
A three-part version number, like 2.4.1, that makes a promise. The last number means a bug fix, the middle one a new feature that breaks nothing, and the first means something may break.
Pinning
Fixing the exact version of something you depend on, by number or by hash, so that it changes only when you decide. A range is a rule. A pin is this one and no other.
SBOM
A list of every component in your software, including what your dependencies depend on, with exact versions. An ingredients label, generated from what you really built.
Artefact
The finished output of a build, stored with a version so that you can move exactly that thing between environments. A bundle, a zip, a container image.
Container
A way to package a program with all the files it needs and run it as an isolated process, so that it behaves the same on your laptop and on a server.
Serverless
You hand a provider your code, and they run it on their machines when requests arrive. There are still servers. They just aren't yours to manage.
Infrastructure as code
Describing your servers, databases and networks in files kept in the repo, and letting a tool make the real world match them, in place of clicking around a console.
Config and secrets
Whatever changes between deploys belongs outside the code: addresses, keys, passwords. The same artefact can then run anywhere, reading its settings from wherever it is running.
Deployment
Putting a new version where it can run. The aim is to make it automatic, small and boring, so that it can happen often.
Continuous delivery
Keeping your software in a state where it could go to production at any moment, so that releasing is a decision and not a project.
Trunk-based development
Everyone merges small changes into one main branch, at least daily, and nobody keeps a branch going for long. Unfinished work stays hidden behind flags.
Feature flag
A condition in your code that turns something on or off, for some or all users, without a deploy. The code ships switched off, and you switch it on when you are ready.
Canary
Sending a small share of real traffic to the new version, comparing it with the old one, and only then sending everyone. If it is bad, few people met it.
Blue-green deployment
Two identical production environments. One serves users while you deploy to the other and check it. Then you switch the traffic across, and the old one stays ready to switch back to.
Rollback
Going back to the previous version after a bad release. Rolling forward is the other choice: shipping a new version with the fix. Rolling back is usually faster, so you stop the harm first and fix it calmly.
Observability
How well you can work out what a running system is doing from the outside, using what it emits, including for problems you didn't predict.
Logs, metrics and traces
Three kinds of signal. A log is a timestamped event. A metric is a number over time, such as requests a second. A trace follows one request through every call it makes.
Structured logging
Writing each log entry as named fields, usually JSON, and not as a sentence. A query can then ask for exact values, without guessing at the wording.
SLI and SLO
An SLI is a measure of how your service is doing, like the share of requests that succeed in time. An SLO is the target you set for that measure, like 99.9% over 30 days.
Error budget
The failure your SLO allows. At 99.9% over 30 days, that is 43.2 minutes of total outage. While there is budget left you ship, and when it is gone you stop and work on reliability.
Alert
A signal that tells a person to act now. A good one fires when users are being hurt and someone can do something about it. A burn-rate alert does this by asking how fast the error budget is going.
On-call
The rota that decides who answers when something breaks, at any hour. That person has to respond quickly, and needs the access and the knowledge to act.
Incident
An unplanned event that is hurting users, or about to, and needs people to coordinate. The work has an order: stop the harm first, then understand why.
Runbook
Written steps for a known situation, which someone tired can follow: what you see, what to check, the exact commands, and when to call for help.
Time to restore
How long it takes to get back to healthy after something breaks. DORA's current version, failed deployment recovery time, counts only failures caused by a change.
Postmortem
A written record of an incident: what happened, what it cost, why, and what changes so that it doesn't happen again. Blameless means it asks how the system allowed this, and doesn't stop at who.
DORA metrics
Five measures of software delivery from Google's DORA research: change lead time, deployment frequency, failed deployment recovery time, change fail rate and deployment rework rate. Speed and stability, side by side.
Change fail rate
The share of deployments that need fixing straight away, by a rollback or a hotfix. Five bad deploys out of fifty is 10%.
The amplifier
DORA's description of what AI does to a software team: it makes strong teams stronger, and makes the problems of struggling ones worse. What decides which is what was already around the tool.

17. Many agents

Parallel agents
Several agents work at the same time on separate parts of a job, each in its own session. You get more done per hour only if the parts really are independent, and only if you can check all of what comes back.
Fan-out
One job is split into pieces, each goes to its own worker at the same moment, and their results are gathered into one answer, which is the fan-in. The whole job takes as long as the slowest worker, plus the gathering.
Orchestrator
An agent whose job is running other agents. It splits the work, briefs each worker, tracks what comes back and judges it, and writes no code itself. A mistake in its brief is repeated by every worker it sends.
Worktree isolation
Each agent gets its own git worktree: a separate folder with its own branch, sharing the same repository. One agent's half-saved file can't break another's test run, and an edit can't quietly overwrite another. They only meet at merge time.
Coordination cost
The time a team spends staying in step and not working: waiting, conflicts, re-reviews, explaining things again. It grows with the pairs of workers and not the workers. Past some point, adding one makes the whole team slower.
Merge queue
Pull requests wait in line, and each is tested on top of main plus everything ahead of it before it merges. Two changes that pass alone and break together get caught before they reach main, not after.
Roles
Give each agent one job with its own prompt, tools and check: one writes specs, one writes code, one tidies, one reviews. Each is told what not to do, so that each check stays with someone who did not write the code.
Evaluator-optimiser
One side writes and the other judges, in a loop. The judge's notes go back to the writer until it passes or the tries run out. It works when the judge has clear criteria, and the result ends up as good as what the judge can see.
Adversarial review
A reviewer whose job is to break the work and not to approve it. It is fair only when each finding must be proved by a run. Without that rule, a reviewer told to find problems will find problems, whether or not they exist.
Ralph loop
The same prompt, fed to a fresh agent, over and over, in a shell loop. Each run does one thing, writes down what it did, and exits. Its memory is on disk. It is cheap to set up, and it has no way of stopping unless you build one.
Long-running agents
An agent working on one goal for hours or days, usually across many sessions that cannot remember each other. What lets it last is outside the model: a plan on disk, notes on progress, tests it can run, and a clean way to start again.
Progress files
A file in the repo saying what has been done and what comes next, which each new session reads first and updates last. It is how a session with no memory finds its place. It is only as true as whatever checks it.
Handoff artefacts
A file one agent commits for the next to pick up: a spec, a diff, a report. Unlike a chat message it outlives the session, has a version, and can be checked. If you pass a commit, the next stage knows exactly what it received.
Checkpoints
A saved state you can go back to when a run goes wrong. Claude Code makes one per prompt, covering files its editing tools changed. Git commits cover everything git tracks. Neither can undo a database change or a sent email.
Scheduled agents
An agent started by a clock or an event and not by a person: triage overnight, check a deploy every five minutes. Nobody is watching when it runs, so it needs narrower permissions than you'd give yourself, and its own way to stop.
Runaway loops
A loop that keeps spending because nothing told it to stop, or a growing session where each turn resends everything before it. Spend rises with every turn, and if nobody is watching, the first sign is the bill.
SwarmForge
A tool for running a line of AI agents, one role each, in separate git worktrees and tmux sessions (tmux keeps several terminals running side by side). Work passes on as committed handoffs, and you approve it at a gate.
pstack
A set of skills by Lauren Tan (poteto) for Cursor and Claude Code. It teaches going deep with one agent first, then running many with proof. It is instructions for the agent you already use, with no runtime of its own, and poteto-mode is the router.
Software factory
A setup where specs and scenarios go in, and agents write, test and ship code, with few or no people reading it. People build the line and its checks. The phrase names a way of working. It is not a product, and not a measured result.
Dark factory
A software factory where no person writes or reads the code, so the lights can stay off. All the trust has to come from evidence such as hidden scenarios and real runs. Few teams claim to do this, and we found no outside audit of any.
Entropy
Agents copy what they find. Good and bad patterns alike spread with every run, so a repo nobody tidies gets less consistent, and faster than people alone would make it. No single change looks wrong. The drift shows up later.
Garbage collection agents
Small background agents that each look for one kind of decay, such as stale docs or a broken convention, and open tiny pull requests to fix it. They pay down entropy in small amounts, so nobody has to hold a clean-up day.
Eval-driven development
Write down what good looks like as a set of scored cases before you change anything, then change the prompt or harness and run them again. An eval is a test of behaviour across many runs. It tells you if the change helped, not how it felt.
When not to
Most work does not need many agents. If it fits in one session, or the parts share files, or you can't check the output, use one. If you could do it in the time it takes to write the brief, use none. Add more only once you have measured a gain.

18. The proof

How strong is this evidence
A rough ranking of how far a kind of study lets you believe its claim: randomised trials near the top, then comparisons over time, then surveys and benchmarks, then single stories. A ranking only makes sense for one question at a time.
Randomised trial
A test where chance decides who or what gets the treatment, so the two groups differ only by luck and by the thing you are testing. That is what lets you say one thing caused another, and not just that they went together.
Confidence interval
A range around a result showing how far it could be from the truth just from the luck of what got sampled. Fewer samples, wider range. It covers bad luck only: a biased study can have a narrow interval around the wrong answer.
Base rate
How common something is before you test for it. When the thing is rare, even a good detector's alarms are mostly wrong, because the many good cases set off more false alarms than the few bad ones set off true ones.
METR's studies
Studies by METR, a non-profit, timing experienced open-source developers on their own real tasks, with chance deciding whether AI was allowed. The 2025 one found them slower. The 2026 follow-up says it couldn't produce a reliable new number.
Perception gap
The distance between how much a tool feels like it helps and how much it measurably does. It can be large, it can point the wrong way, and the person inside it can't see it from there.
Skill atrophy
Losing a skill, or never building it, because something else does the work for you. With agents, the worry is that you can ship code you can't explain or debug, and that you don't notice until the agent gets stuck and so do you.
Trust surveys
Surveys asking developers how far they trust AI tools. The number that gets quoted depends mostly on how the question was asked and which answers someone decided to count as trust.
DORA on AI
Google Cloud's DORA research on how software teams deliver. Its 2025 report, from a survey of nearly 5,000 technology professionals, calls AI an amplifier: it makes strong teams stronger and struggling teams worse.
Output isn't delivery
More code isn't more software shipped. Output is what gets produced: lines, commits, pull requests. Delivery is what reaches people and does its job. Agents can raise the first a long way while the second moves much less.
Vendor studies
Research published by a company that sells something in the same area. It can be perfectly good work. You say who paid when you quote it, and you read what it measured with that in mind.
What nobody has measured
The questions with no good study behind them yet. For agent-written code the biggest is this: does it cause more production incidents? We found no primary, peer-reviewed measurement, and saying so is a stronger answer than filling the gap.
Reading a productivity claim
Four questions to ask of any number about AI and productivity, in this order: who measured it, what was it compared with, what did they count, and who paid. A claim that survives usually comes out smaller and more useful.
Prediction or measurement
A measurement says what happened, to what, compared with what. A prediction says what will happen. Both can be worth hearing, and they need different treatment: you check a measurement, and with a prediction you ask what would show it right or wrong, and when.
The claim you can defend
A short paragraph you can say out loud in which every sentence points at something you can open: a file, a commit, a failing run. If a sentence has nothing behind it, you either drop it or go and do the work.
A repo worth showing
One public project small enough to read in ten minutes, where the process is visible as well as the result: the brief, the checks, the history, and what went wrong. This is our suggestion. We found no employer saying which artefact persuades them.
A commit trail
A project's history read as evidence: what changed, in what order, and why. A good trail shows small steps with reasons, checks arriving after mistakes, and things being undone. One giant commit shows nothing.
AGENTS.md as evidence
Your instructions file read as a record of what has gone wrong. A line naming a real command, file or past mistake shows someone was paying attention. A line like "write clean code" shows nothing at all.
The log of past failures
A running list of mistakes: what went wrong, what now prevents it, and proof that the check fails on the old code. It shows you noticed a failure, generalised it, and closed it off.
Decision records as evidence
A short dated note of a decision: what you chose, what you rejected, and why. As evidence, it shows a person made a call the agent couldn't make alone, and it lets someone ask you about it a year later.
Reviewing live in an interview
Reading code you didn't write in front of someone, saying what you are looking for and what you aren't getting to. Going by what hiring teams write, they are watching your order and your honesty at least as much as what you find.
Debugging without the agent
Finding and fixing a bug yourself with the agent off: read the error, make a guess, test the guess, narrow it down. You don't have to be quick. You have to have a method, and be able to say what it is as you go.
Explaining trade-offs
Saying what you chose, what you gave up for it, and when you would choose differently. If you can't name the cost of a decision, you probably didn't make it.
Saying what you don't know
Saying plainly where your knowledge and your evidence stop. "I don't know, and here is how I would find out" is a complete answer. An absolute such as "always" or "fully tested" only needs one counter-example to sink you.
Employer AI policies
What a company says about using AI at work and in its hiring. They differ, often within one company: the same process may forbid AI in one round and expect it in the next. So you ask each time, and never assume.
Take-homes in the agent era
Work you do in your own time for a hiring process. Agents can now finish many of them, so companies are banning AI on them, redesigning them, or moving to scoped builds and live follow-up. Expect to defend every line.
Red flags interviewers look for
What interviewers report seeing when someone's claim to work with agents is hollow: no plan, permission checks off, a skimmed diff, stuck the moment the agent is stuck. A follow-up question or two is usually all it takes to find out.
The hard questions
The 57 questions a sceptical engineer could ask about how you build with agents, the same ones as the interview room. Only a few are asked verbatim by a source, and most are our own reasoning. The bench tells you which is which.
What to do in your first week
Learn the rules on AI and data. Read before you generate. Find out what blocks a merge. Ship something small and reviewed. Ask what failed last. These are the same habits as this course, on code you don't own yet.
What you can now say
Only what you can point at. If you did the work, it comes out short: my agents write most of the code, here is how I brief them, here is what stops bad work, here is what still gets through, and here is how I find out.

The workshop

Name a word, or describe what you mean in everyday language.